Beyond the Gender Wage Gap

Much attention, both academically and journalistically, has been paid to the “Gender Wage Gap” (e.g. http://inequality.stanford.edu/_media/pdf/key_issues/gender_research.pdf). As this is well-tred territory, our team is interested in looking beyond the gender wage gap and analyzing the inter-gender wage gap. That is, within women in the workforce, are there identifiables gaps in earnings? The following report both confirms a gender wage gap across occupations and identifies gaps among several characteristics of women working within each occupation.

Where is the gap?

Since we know there is a significant wage gap between different professions, we used occupation as a category for our data. We seperated the occupations by groups. Within each group, we divided the men and women and compared their weighted mean.

We started by importing the data set from the United States Census Bureau.

#Importing Data Set
# www2.census.gov/programs-surveys/acs/data/pums/2014/1-Year/csv_pus.zip
ss14pusa = read.csv(file.choose(),header=TRUE)  # read csv file
ss14pusb = read.csv(file.choose(),header=TRUE)

For our anaylsis, we used dplyr, plyr, dplyr, rcokeh, ggplot2, plotly, car, survey, and googleVis.

The following shows the columns we imported.

We renamed and categorized multiple categories for readablilty.

Note: we used eight high paying occupation to categorize jobs

Based on the eight occupations, we plot the weighted mean of men and women to compare the gap.

From the graph, we see there is a significant difference between men and women over all occupations. To gain a better understanding we graphed them by percentage from the weighted mean of both genders.

Oberservations:

  1. Medical occupations has the largest disperity between men and women

  2. Women in legal occupations are the closest to the median

In this report, we will investigate 5 probable causes to determine which groups of women will most likely succeed or fail. These categories are: Marriage Status, Motherhood, Location, Race, and Education.

Familial Responsibilities

Our next variable of interest is women’s marital statuses. A common explanation of the gender wage gap is that women make the decision with their families to shift their focus to household responsibilities. We’ll be looking at the effect of marriage and motherhood seperately first, then looking how marital statuses of mothers affect their earnings.

Marital Status

Below we analyse the effect of marital status on mean income for women across all occupations, as well as within occupations.


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_occp)

Residuals:
   Min     1Q Median     3Q    Max 
-56107 -11573  -1470   8035 231989 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -39977.664   3357.450 -11.907  < 2e-16 ***
MarriageWidowed        -5058.692   1430.698  -3.536 0.000415 ***
MarriageDivorced       -3058.190   1342.701  -2.278 0.022842 *  
MarriageSeperated      -8106.266   1479.165  -5.480 4.72e-08 ***
MarriageNever Married    557.144   1337.027   0.417 0.676935    
Age                     4089.016    134.708  30.355  < 2e-16 ***
I(Age^2)                 -38.882      1.275 -30.488  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21170 on 2232 degrees of freedom
Multiple R-squared:  0.2979,    Adjusted R-squared:  0.296 
F-statistic: 157.8 on 6 and 2232 DF,  p-value: < 2.2e-16


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_FIN)

Residuals:
   Min     1Q Median     3Q    Max 
-35099  -8154   -769   6758  85196 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -36346.096   6420.514  -5.661 3.61e-08 ***
MarriageWidowed        -7156.318   2631.738  -2.719  0.00694 ** 
MarriageDivorced       -2261.388   2542.871  -0.889  0.37457    
MarriageSeperated     -15267.284   2763.424  -5.525 7.33e-08 ***
MarriageNever Married   2543.383   2558.912   0.994  0.32108    
Age                     3941.532    258.084  15.272  < 2e-16 ***
I(Age^2)                 -39.041      2.435 -16.032  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 14470 on 291 degrees of freedom
Multiple R-squared:  0.5055,    Adjusted R-squared:  0.4953 
F-statistic: 49.57 on 6 and 291 DF,  p-value: < 2.2e-16


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_ENG)

Residuals:
   Min     1Q Median     3Q    Max 
-71787 -13616  -1922   6880 221919 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -67401.667  18767.237  -3.591 0.000411 ***
MarriageWidowed        -1410.202   7393.487  -0.191 0.848921    
MarriageDivorced       -4852.957   6009.505  -0.808 0.420283    
MarriageSeperated     -16473.248   7418.879  -2.220 0.027478 *  
MarriageNever Married  -1392.858   5878.545  -0.237 0.812939    
Age                     5917.840    827.959   7.148 1.50e-11 ***
I(Age^2)                 -59.961      8.655  -6.928 5.36e-11 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 30550 on 206 degrees of freedom
Multiple R-squared:  0.2152,    Adjusted R-squared:  0.1924 
F-statistic: 9.416 on 6 and 206 DF,  p-value: 3.912e-09


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_MED)

Residuals:
   Min     1Q Median     3Q    Max 
-35762  -7890    447   6423 117974 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -19061.330   6542.696  -2.913 0.003825 ** 
MarriageWidowed       -10048.240   2875.561  -3.494 0.000542 ***
MarriageDivorced       -1420.377   2803.367  -0.507 0.612733    
MarriageSeperated      -9171.092   3002.385  -3.055 0.002441 ** 
MarriageNever Married   -419.022   2828.361  -0.148 0.882317    
Age                     3019.839    255.543  11.817  < 2e-16 ***
I(Age^2)                 -28.188      2.342 -12.037  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 16640 on 323 degrees of freedom
Multiple R-squared:  0.3316,    Adjusted R-squared:  0.3192 
F-statistic:  26.7 on 6 and 323 DF,  p-value: < 2.2e-16


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_SCI)

Residuals:
   Min     1Q Median     3Q    Max 
-68959 -10504   -932   8858  95689 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -77292.909  10726.610  -7.206 7.04e-12 ***
MarriageWidowed        -6390.342   4489.513  -1.423    0.156    
MarriageDivorced       -2419.314   3934.713  -0.615    0.539    
MarriageSeperated       2882.259   4602.021   0.626    0.532    
MarriageNever Married   2465.396   3899.844   0.632    0.528    
Age                     5640.076    444.813  12.680  < 2e-16 ***
I(Age^2)                 -53.246      4.334 -12.286  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21450 on 246 degrees of freedom
Multiple R-squared:  0.4066,    Adjusted R-squared:  0.3922 
F-statistic:  28.1 on 6 and 246 DF,  p-value: < 2.2e-16


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_MGR)

Residuals:
   Min     1Q Median     3Q    Max 
-40481  -9893   -582   5931 212526 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -44162.963   8226.978  -5.368 1.51e-07 ***
MarriageWidowed        -2612.919   3617.947  -0.722   0.4707    
MarriageDivorced       -4895.286   3620.382  -1.352   0.1773    
MarriageSeperated      -8413.422   3807.248  -2.210   0.0278 *  
MarriageNever Married  -1116.802   3591.031  -0.311   0.7560    
Age                     4377.509    326.101  13.424  < 2e-16 ***
I(Age^2)                 -40.301      3.009 -13.391  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21380 on 327 degrees of freedom
Multiple R-squared:  0.3585,    Adjusted R-squared:  0.3467 
F-statistic: 30.46 on 6 and 327 DF,  p-value: < 2.2e-16


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_LGL)

Residuals:
   Min     1Q Median     3Q    Max 
-38365  -8400  -2126   6518 159634 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -39807.860   9552.619  -4.167 4.26e-05 ***
MarriageWidowed       -11672.166   3875.330  -3.012  0.00286 ** 
MarriageDivorced       -4590.456   3398.000  -1.351  0.17795    
MarriageSeperated      -3691.867   3913.706  -0.943  0.34644    
MarriageNever Married     50.710   3386.857   0.015  0.98807    
Age                     3548.182    390.813   9.079  < 2e-16 ***
I(Age^2)                 -32.067      3.797  -8.446 2.56e-15 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 18510 on 248 degrees of freedom
Multiple R-squared:  0.274, Adjusted R-squared:  0.2565 
F-statistic:  15.6 on 6 and 248 DF,  p-value: 3.508e-15


Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_BUS)

Residuals:
   Min     1Q Median     3Q    Max 
-40066 -10052  -1659   6642 173126 

Coefficients:
                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -33142.936   8924.930  -3.714 0.000246 ***
MarriageWidowed         2308.734   3704.024   0.623 0.533580    
MarriageDivorced       -1095.901   3625.929  -0.302 0.762688    
MarriageSeperated     -10299.949   3862.286  -2.667 0.008092 ** 
MarriageNever Married   3826.334   3582.032   1.068 0.286327    
Age                     3701.176    355.322  10.416  < 2e-16 ***
I(Age^2)                 -36.125      3.345 -10.800  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 20210 on 287 degrees of freedom
Multiple R-squared:  0.303, Adjusted R-squared:  0.2884 
F-statistic: 20.79 on 6 and 287 DF,  p-value: < 2.2e-16

Observations:

  1. Overall,widowed and seperated women make significantly less than married women when occupations are pooled.

  2. Marital status has no effect on earning for women in the scientific field

  3. Interestingly, for most occupations where marital status is significant, women in their profession who have never been married earn more than married women, whereas widowed and seperated women earn significantly less. Perhaps widowed or seperated women are more likely to have children than never married women, and thus must shoulder more responsibilities outside of work.

Motherhood

After investigating how marriage status affect women’s income, we looked into the presence and age of children owned by the women to determine how it might correlate to women’s income. We expect women with Children under 6 may have less working hours and thus lower income (reasoning: when a child is young the women of the house is more likely to stay home with their children. As we see the children grow, we expect a trend for women to earn the higher.) Furthermore, we may also want to figure out how occupation and age for women with children affect their income.

At first, we want to have a glance at the income level of the different groups of females. Basically females are divided into four categories regarding the presence and age of Children: Females with Children under 6, Females with Children from 6 to 17, Females with Children under 6 and above 6, Females with No Children. Thus we simply creat a bar chart to illustrate the income difference.

#Computer
Women_CMM<-filter(Data_women, Occupation =="CMM")
Data_wed_CMM <- ddply(Women_CMM, .(Marriage, Age), summarise, MEAN = weighted.mean(Income, Weight, na.rm = T))
CMM <- plot_ly(Data_wed_CMM, x = Age, y = MEAN, mode = "markers", opacity = .4, color = Marriage) 
CMM <-add_trace(CMM,y = fitted(loess(MEAN ~ Age + as.numeric(Marriage))) , x = Age, color = Marriage) 
layout(CMM, title = "Women in Computer Science")

summary(lm(MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_CMM))

Call:
lm(formula = MEAN ~ Marriage + Age + I(Age^2), data = Data_wed_CMM)

Residuals:
   Min     1Q Median     3Q    Max 
-49094  -9844     78   6958 121180 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)    
(Intercept)           -47534.01    8781.27  -5.413 1.43e-07 ***
MarriageWidowed        -2742.11    3575.69  -0.767    0.444    
MarriageDivorced       -2754.09    3335.19  -0.826    0.410    
MarriageSeperated      -4313.13    3625.43  -1.190    0.235    
MarriageNever Married  -1096.28    3334.11  -0.329    0.743    
Age                     4792.97     364.29  13.157  < 2e-16 ***
I(Age^2)                 -46.82       3.59 -13.041  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 18000 on 255 degrees of freedom
Multiple R-squared:  0.4061,    Adjusted R-squared:  0.3921 
F-statistic: 29.06 on 6 and 255 DF,  p-value: < 2.2e-16

Observations: The bar chart verifies our guess. Women with children 6 to 17 has obviously higher Average Income as they have more working experience and do not need to spend too much time to take care of young children. On the other hand, women with Children of both ages have slightly lower income, which is also reasonable as they may not have too much time in work.

Next, in order to better understand why women with children 6 to 17 have higher income and whether it has anything to do with age, we are going to study how the income change for different groups of women through out age. Basically we try to analyze by line chart to see the income trend and compare.

Data_women <- filter(Data, Gender == 2)
Data_women$Agegroup <- cut(as.numeric(Data_women$Age), breaks = c(20,25,30,35,40,45,50,55,60,65))
Data_women <- filter(Data_women, Age > 20 & Age < 66)
MotherHood=select(Data_women, Income,Children)
detach(package:plyr)
GroupedMotherHood <-
  MotherHood %>%
  na.omit() %>%
  group_by(Children) %>%
  summarize(
    AvgIncome = mean(Income)
  )
GroupedMotherHood$Children<-factor(GroupedMotherHood$Children, levels = c("1","2","3","4"), c('Children under 6','Children from 6 to 17','Children under 6 and above 6','No Children'))
ggplot(GroupedMotherHood, aes(x=Children, y=AvgIncome)) +
  geom_bar(width=.5, stat="identity")+
  guides(fill=FALSE) +
  xlab("MotherHood") + ylab("Mean Income") +
  coord_cartesian(ylim = c(50000,70000)) +
  ggtitle("Income for Motherhood")

Observations: 1. Before 45-50 years old, there is an abvious increasing trend of income basically for all groups. And after that age, average income begins to decrease or stablize. 2. Surprisingly, for the same age group, women with Children under 6 have higher income. While women with children from 6 and 17 have higher income after 45 years old, which might be the reason this group has higher average income. On the other hand, women with no children doesn’t earn less than other groups at younger age groups, but their income become stable and less than others after 40 years old.

Next, we wanted to see how the working hours related to the income of women in different group. Will women with children from 6 to 17 have more working hours and generate higher income? Thus we want to use bubble chart to integrate working hours, average income, the group count in a bubble chart so that all the information can be gained in the same graph.

MotherHood=select(Data_women, Income,Children,Agegroup)
#detach(package:plyr)
GroupedMotherHood <-
  MotherHood %>%
  na.omit() %>%
  group_by(Children,Agegroup) %>%
  summarize(
    AvgIncome = mean(Income)
  )
### Line Chart with regard to Age
GroupedMotherHood$Children<-factor(GroupedMotherHood$Children, levels = c("1","2","3","4"), c('Children under 6','Children from 6 to 17','Children under 6 and above 6','No Children'))
#ggplot(GroupedMotherHood, aes(x=Agegroup, y=AvgIncome,fill=Children)) +
#  geom_bar(width=.5, stat="identity")+
#  xlab("Age Group") + ylab("Mean Income") +
#  ggtitle("Income for Motherhood")
ggplot(GroupedMotherHood, aes(x=Agegroup, y=AvgIncome,group=Children,colour=Children)) +
  geom_line()+
  geom_point()+
  #guides(fill=FALSE) +
  xlab("Age Group") + ylab("Mean Income") +
  ggtitle("Income for Motherhood")

Observations: 1. When work_hours smaller than 60Hrs, Avg Income tend to be positively related to work hour, which agrees with our common knowledge. Most women concentrate around 40 working hours. 2. There are generally more females with no Children in this survey as green circles are generally larger in size. Also it can be observed there are much more women with no children working more than 50 hours compared to other groups. On the other hand, there are basically less women with children from both age groups. 3. Females with Children from 6 to 17 often have higher avg income. While for the same working hour level, females with no children are frequently have lower average income.

Next we want to investigate whether the income difference among four grouops of female have any relationship to their occupation. Therefore we use this chart to compare the income for four groups of women in different occupations. Basically, darker color represent higher income and larger size indicate larger group size.

MotherWorking=select(Data_women, Income,Children,Work_hours)
#detach(package:plyr)
GroupedMotherWorking <-
  MotherWorking %>%
  na.omit() %>%
  group_by(Children,Work_hours) %>%
  summarize(
    AvgIncome = mean(Income),
    count=n()
  )
GroupedMotherWorking$Children<-factor(GroupedMotherWorking$Children, levels = c("1","2","3","4"),labels= c('Children under 6','Children from 6 to 17','Children under 6 and above 6','No Children'))
library(plotly)
# note how size is automatically scaled and added as hover text
plot_ly(GroupedMotherWorking, x = Work_hours, y = AvgIncome,size=sqrt(count), color = Children,mode = "markers",hoverinfo = "text",text = paste("AvgIncome:",AvgIncome,"<br>","Count:",count,"<br>"))

Observations: 1. Females with Children from 6 to 17 usually tend to have higher average income as the dot has darker color for several occupations. However, females with no children and females with children of both age group have lower income. 2. Occupation of ENG, MGR and CMM usually tend to have higher salary. On the other hand, female in LGL field always have lower salary, especially for females with Children under 6 working in LGL. 3. It confirms again that there are more females with no Children.

Conclusion: After conducting analysis on the income of females of different groups regarding the children presence and age as well as interacting with some other variables, we find out that females with no children and females with Children under 6 and above 6 may have lower income compared to the other two groups.

Marital statuses of mothers

Observations: We can see in the summary results of the interaction between marital status and motherhood, single mothers earn significantly less when occupations are pooled and age is controlled.

Education

We expect that educational attainment would affect the women’s income. We may want to figure out which degree is the most important factor to earn more than the median income. Furthermore, we will see which occupation has the largest/smallest “below median group” within each educational attainment.

We divided female into 2 groups (>=$60,000 vs <60,000) using weighted median income for working class. ($60,000) We will see the proportion of these 2 groups for each educational attainment.

MotherMaritalOccupation=select(Data_women, Income,Children,Occupation, Marriage, Age)
MotherMaritalOccupation <- na.omit(MotherMaritalOccupation)
MotherMaritalOccupation$Children <- ifelse(MotherMaritalOccupation$Children == 4, 0, 1)
#detach(package:plyr)
GroupedMotherMaritalOccupation <-
  MotherMaritalOccupation %>%
  na.omit() %>%
  group_by(Children,Occupation, Marriage, Age) %>% 
  summarize(
    AvgIncome = mean(Income),
    count=n()
  ) 
GroupedMotherMarital <-
  MotherMaritalOccupation %>%
  na.omit() %>%
  group_by(Children, Marriage, Age) %>% 
  summarize(
    AvgIncome = mean(Income),
    count=n()
  ) 
ggplot(GroupedMotherMarital,aes(y = AvgIncome, x =Age,colour=as.factor(Children))) +
geom_point() + geom_smooth(method="loess", fill=NA) + facet_wrap(~Marriage, scales= "free")

summary(lm(AvgIncome ~ Age + I(Age^2) + Children*Marriage, data = GroupedMotherMaritalOccupation))

Call:
lm(formula = AvgIncome ~ Age + I(Age^2) + Children * Marriage, 
    data = GroupedMotherMaritalOccupation)

Residuals:
   Min     1Q Median     3Q    Max 
-65888 -10493  -1879   7328 384166 

Coefficients:
                                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)                    -59323.906   5257.629 -11.283  < 2e-16 ***
Age                              4987.877    254.145  19.626  < 2e-16 ***
I(Age^2)                          -47.777      2.929 -16.313  < 2e-16 ***
Children                         2882.840   1628.541   1.770 0.076801 .  
MarriageWidowed                 -6785.321   1847.179  -3.673 0.000244 ***
MarriageDivorced                -2517.617   1618.366  -1.556 0.119902    
MarriageSeperated               -8634.582   1722.751  -5.012 5.71e-07 ***
MarriageNever Married            3243.048   1600.407   2.026 0.042818 *  
Children:MarriageWidowed        -6511.152   2805.557  -2.321 0.020368 *  
Children:MarriageDivorced       -4680.108   2365.606  -1.978 0.047980 *  
Children:MarriageSeperated      -1087.083   2514.920  -0.432 0.665590    
Children:MarriageNever Married -10540.040   2354.884  -4.476 7.91e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21470 on 2842 degrees of freedom
Multiple R-squared:  0.2619,    Adjusted R-squared:  0.2591 
F-statistic: 91.69 on 11 and 2842 DF,  p-value: < 2.2e-16

Observations:

  1. Without college degree, about 80% of them earn less than median income.

  2. With master’s or doctor’s degree, about 40% of them earn less than median income.

Next, we use a linear regression.

require(plyr)
#Calculate weighted median to split income below/above
Data_w<-svydesign(id = ~1, weights = ~Data$Weight, data = Data)
svyquantile(~Data$Income, Data_w, c(.25,.5,.75))
             0.25   0.5  0.75
Data$Income 35000 60000 92000
##Median income=$60000
#split income below/above
Temp$Income_m<-ifelse(Temp$Income>=60000,">=$60,000","<$60,000")
Data_women2<-subset(Temp,Gender=='2')
attach(Data_women2)
Data_women2<-data.frame(Education,Occupation,Income_m,Weight)
detach(Data_women2)
#get the summary table-education
Data_women_w<-svydesign(id = ~1, weights = ~Data_women2$Weight, data = Data_women2)
t1<-prop.table(svytable(~Income_m+Education, Data_women_w),2)
barplot(t1, main = "Below/Above median income women by Educational attainment",col = c("mistyrose", "lavender"),
xlab = "Educational attainment", names = c("~g8", "g9~nodegree","ass/bach","prof/mas","doc"), 
ylab = "proportion", legend = c("<$60,000", ">=$60,000"), 
args.legend = list(title = "income", x = "topright", cex = 1), ylim = c(0, 1.5))

Observations:

  1. factor2 (grade9~college_no_degree) is not significant.

  2. Interpretation for factor3: “associate/bachelor’s degree”, versus “~grade8”(baseline), multiplies the odds of being “>=$60000” group by exp(0.94372)

  3. We can apply the same interpretation for factor 4,5,6.

  4. Within college, master, doctor’s degree, the chance of being in “>=$60000” group increases at higher educational attainment.

  5. However, the gap between master’s and doctor’s degree is relatively small.

To futher understand the effect, we are going to break down each education by occupation.

fit_edu<-svyglm(factor(Income_m) ~ factor(Education), design = Data_women_w,family=binomial)
non-integer #successes in a binomial glm!
summary(fit_edu)

Call:
svyglm(formula = factor(Income_m) ~ factor(Education), design = Data_women_w, 
    family = binomial)

Survey design:
svydesign(id = ~1, weights = ~Data_women2$Weight, data = Data_women2)

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)        -1.30179    0.11634 -11.189  < 2e-16 ***
factor(Education)2 -0.06833    0.11711  -0.584     0.56    
factor(Education)3  0.94372    0.11663   8.091 5.94e-16 ***
factor(Education)4  1.78284    0.11708  15.228  < 2e-16 ***
factor(Education)5  2.03576    0.12210  16.673  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1.000005)

Number of Fisher Scoring iterations: 4

Observations:

  1. Within “~grade8”, “FIN:finance” has the largest <$60,000 group.

  2. “CMM:computer occs” has the smallest <$60,000 group.

Observations:

  1. Within “grade9~college_no_degree”, “SCI:science” has the largest <$60,000 group.

  2. “CMM:computer occs” has the smallest <$60,000 group.

Observations:

  1. Within “associate/bachelor”, “LGL:legal” has the largest <$60,000 group.

  2. “CMM: computer occs” has the smallest <$60,000 group.

Observations:

  1. Within “Master”, “LGL:legal” has the largest <$60,000 group.

  2. “CMM:computer occs” has the smallest <$60,000 group.

Observations:

  1. Within “Doctor”, “LGL:legal” has the largest <$60,000 group.

  2. “CMM:computer occs” has the smallest <$60,000 group.

Conclusions:

  1. Women without college degree is more likely to earn less than median income.

  2. (-) At any educational attainment,CMM:computer occs has the smallest <$60,000 group.

  3. (+) With the bachelor/master/doctor’s degree LGL:legal has the largest >=$60,000 group.

Regional

You cannot choose where you were born, but you can choose where you live. Different places sends different messages and attracts different people. In this section we are interested to see regional effect on women’s income in the US. The main question here is: in which locations are women better or worse off?

First, we want to look at women’s income boxplots in all 4 regions to better understand women’s income distribution.

The boxplots of women’s income show that despite that all distributions are highly skewed to the right, the Northeast Region has the highest women’s income level of all 4 regions, followed by the West; Midwest has the lowest women’s income level, whereas South is only slightly better off than that. Then we will break down to state level to investigate further on women’s income level.

Income levels can be affected by many things. Cost of living is one of them. For example, In New York, everthing cost a little more than many other parts of the US, so people will only thrive by earning more money. Therefore, in order to remove the effect of cost of living that differs in different states, we calculate the percentage of median of each woman’s income by state and draw boxplot according to that.

Error in eval(expr, envir, enclos) : object 'Region' not found

From this irisdescent boxplot by state, we can see that New York definitely goes ahead (despite that its cost of living is already high), so does Connecticut with more large extreme values; however California has the highest upper whisker and largest portion of upper middle income; Utah and Wyoming are the worst off.

Then we want to decide locations where women will thrive most financially (relatively to men), so we plot women’s median of percentage income by state in a US map, which shows the percentage of statewise median that half of women has income below. In perfect equal-gender scenarios, the percentage should be 1, which means half of women have income below the exact statewise median.

This map clearly shows that Utah is where women thrive most financially (relatively to men). Half of women in Utah have income below 68.97% of state median, compared to 100% in the perfect equal-gender situation. Surprisingly (at least to us), D.C. tops among all states with a 93%, followed by Nevada 92% and Arizona 90%.

Conclusion: Women’s income distributions in each state are all highly skewed to the right with lots of large extreme values. 1. The Northeast Region has the highest women’s income level of all 4 regions in the US. 2. After excluding statewise differences e.g. cost of living, women in New York and Connecticut tend to have higher incomes, California has the highest upper whisker and largest portion of upper middle income, and Utah and Wyoming are the worst off. 3. By comparing women’s income medians with state medians, we see that half of Utah’s women have income below 69% of state median, which is the lowest percentage among all states. Woman in D.C., Nevada, and Arizona have income medians closest to state median, with percentage above 90%, whereas other states’ are much lower.

Race

Over the years, there has been an increase awareness on the women wage gap and racial social issues. We wanted to understand the effects of a women’s race could potentially have on a women’s career.

First, we broke down the data of women by race.

From the pie chart, we determined that majority of women in the work force are white. To see how this compares to the national average, we compared this chart to the overall race breakdown of the country. Our assumption is that women should make up half of the working force for all races.

Observation:

  1. From the table, we can gather that Black women are 11% higher than the half of the Black workforce. This means more black women are working than man.

  2. All other races have a relatively small difference.

  3. Workforce groups with more men than women are White, Asian, and Others.

We also want to look into how women perform in the occupation. We broke up this into three categories:

  1. Women who perform under the weighted mean of women

  2. Women who perform above the weighted mean of both genders

  3. Women who perform above the weighted mean of men

These categories will be classified as below, meet, and exceed respectively.

From the graph, we notices that majority of occupation were not meeting the criteria. To gain a better understand, we took into account he population size.

is.na() applied to non-(list or vector) of type 'NULL'is.na() applied to non-(list or vector) of type 'NULL'is.na() applied to non-(list or vector) of type 'NULL'is.na() applied to non-(list or vector) of type 'NULL'is.na() applied to non-(list or vector) of type 'NULL'is.na() applied to non-(list or vector) of type 'NULL'is.na() applied to non-(list or vector) of type 'NULL'is.na() applied to non-(list or vector) of type 'NULL'

Oberservations:

  1. Asians women earn significantly higher income than other races.

  2. The average for women is very close the White women because they account for most of the workforce.

  3. There are no groups of women that are higher than the median of men

From the plot, we also see a lot of minority groups toward the bottom. The frequency for these froups were often very small. To help gain a better understanding, we took out all groups with less than 50 people in the category.

Obeservations:

  1. Except for Asians and Blacks, all other minority groups earned significantly less than the median.

  2. Black Women earn less than White womens for all occupations, except legal.

  3. Lawyers would have the most equal pay relative to the rest of the occupations.

From our analysis, we learned the following breakdown of women in the workforce:

Level Race of Women
Below Black, American Indian, Tribe specified, Native Hawaiian, Other, Two or more races
Meet Asian, White
Exceed None

Through these results, their is a significant gap in income for women regardless to race.

Appendix

Using Survey Weights

We were trying to determine whether or not to use survey weights. To help our research we used http://tophcito.blogspot.co.at/2014/04/social-science-goes-r-weighted-survey.html for reference. All samples were assigned one. The sample with qualities more frequent was assigned a lower number, vice Versa. Respondents that belong to groups that have been sampled perfectly receive a weight of 1. This solution is called post-stratification, because it computes weights based on group (or stratum) characteristics, like the distribution of age or gender proportions.

DSOR_W_Freq_filtered <- filter(DSOR_W_Freq, x.Freq > 50)
Base_fill <- ggplot(DSOR_W_Freq_filtered, aes(x=Race,y=MEAN),colour = factor(DSOR_W_Freq_filtered$Race)) +
            facet_grid(. ~ Occupation)+
            geom_point(aes(size = DSOR_W_Freq_filtered$x.Freq,color = factor(DSOR_W_Freq_filtered$Race)))+
            labs(title = "Histogram by Race of Females using Size")+
            geom_hline(aes(yintercept = MEAN),colour="deeppink1",data=Data_sex_occp_women)+
            geom_hline(aes(yintercept = MEAN),colour="blue",data=Data_sex_occp_men)+
            geom_hline(aes(yintercept = MEAN),colour="green",data=Data_occu)
ggplotly(Base_fill)

From our results, the survey weights would be insignificant relative to the data. The difference for each income level between unweighted and weighted is too small.

LS0tDQp0aXRsZTogIldvbWVuIGluIFdvcmsgRm9yY2UiDQphdXRob3I6ICJLYW5naHVpIEppYW5nLCBFcmljYSBLaWxicmlkZSwgSGF5b3VuZyBLaW0sIFdhbnlpIFpoYW5nLCBhbmQgQ2F0aGVyaW5lIFpoYW8iDQpkYXRlOiAiU2VwdGVtYmVyIDIxIDIwMTYiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KI0JleW9uZCB0aGUgR2VuZGVyIFdhZ2UgR2FwDQoNCk11Y2ggYXR0ZW50aW9uLCBib3RoIGFjYWRlbWljYWxseSBhbmQgam91cm5hbGlzdGljYWxseSwgaGFzIGJlZW4gcGFpZCB0byB0aGUgIkdlbmRlciBXYWdlIEdhcCIgKGUuZy4gaHR0cDovL2luZXF1YWxpdHkuc3RhbmZvcmQuZWR1L19tZWRpYS9wZGYva2V5X2lzc3Vlcy9nZW5kZXJfcmVzZWFyY2gucGRmKS4gQXMgdGhpcyBpcyB3ZWxsLXRyZWQgdGVycml0b3J5LCBvdXIgdGVhbSBpcyBpbnRlcmVzdGVkIGluIGxvb2tpbmcgYmV5b25kIHRoZSBnZW5kZXIgd2FnZSBnYXAgYW5kIGFuYWx5emluZyB0aGUgaW50ZXItZ2VuZGVyIHdhZ2UgZ2FwLiBUaGF0IGlzLCB3aXRoaW4gd29tZW4gaW4gdGhlIHdvcmtmb3JjZSwgYXJlIHRoZXJlIGlkZW50aWZpYWJsZXMgZ2FwcyBpbiBlYXJuaW5ncz8gVGhlIGZvbGxvd2luZyByZXBvcnQgYm90aCBjb25maXJtcyBhIGdlbmRlciB3YWdlIGdhcCBhY3Jvc3Mgb2NjdXBhdGlvbnMgYW5kIGlkZW50aWZpZXMgZ2FwcyBhbW9uZyBzZXZlcmFsIGNoYXJhY3RlcmlzdGljcyBvZiB3b21lbiB3b3JraW5nIHdpdGhpbiBlYWNoIG9jY3VwYXRpb24uDQoNCiNXaGVyZSBpcyB0aGUgZ2FwPw0KDQpTaW5jZSB3ZSBrbm93IHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgd2FnZSBnYXAgYmV0d2VlbiBkaWZmZXJlbnQgcHJvZmVzc2lvbnMsIHdlIHVzZWQgb2NjdXBhdGlvbiBhcyBhIGNhdGVnb3J5IGZvciBvdXIgZGF0YS4gV2Ugc2VwZXJhdGVkIHRoZSBvY2N1cGF0aW9ucyBieSBncm91cHMuIFdpdGhpbiBlYWNoIGdyb3VwLCB3ZSBkaXZpZGVkIHRoZSBtZW4gYW5kIHdvbWVuIGFuZCBjb21wYXJlZCB0aGVpciB3ZWlnaHRlZCBtZWFuLg0KDQoNCldlIHN0YXJ0ZWQgYnkgaW1wb3J0aW5nIHRoZSBkYXRhIHNldCBmcm9tIHRoZSBVbml0ZWQgU3RhdGVzIENlbnN1cyBCdXJlYXUuDQpgYGB7ciBlY2hvPT1GQUxTRX0gDQojSW1wb3J0aW5nIERhdGEgU2V0DQojIHd3dzIuY2Vuc3VzLmdvdi9wcm9ncmFtcy1zdXJ2ZXlzL2Fjcy9kYXRhL3B1bXMvMjAxNC8xLVllYXIvY3N2X3B1cy56aXANCnNzMTRwdXNhID0gcmVhZC5jc3YoZmlsZS5jaG9vc2UoKSxoZWFkZXI9VFJVRSkgICMgcmVhZCBjc3YgZmlsZQ0Kc3MxNHB1c2IgPSByZWFkLmNzdihmaWxlLmNob29zZSgpLGhlYWRlcj1UUlVFKQ0KYGBgDQpGb3Igb3VyIGFuYXlsc2lzLCB3ZSB1c2VkIGRwbHlyLCBwbHlyLCBkcGx5ciwgcmNva2VoLCBnZ3Bsb3QyLCBwbG90bHksIGNhciwgc3VydmV5LCBhbmQgZ29vZ2xlVmlzLiAgDQpgYGB7ciBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojTGlicmFyaWVzDQpyZXF1aXJlKGRwbHlyKQ0KcmVxdWlyZShwbHlyKQ0KcmVxdWlyZShkcGx5cikNCnJlcXVpcmUocmJva2VoKQ0KcmVxdWlyZShnZ3Bsb3QyKQ0KcmVxdWlyZShwbG90bHkpDQpyZXF1aXJlKGdvb2dsZVZpcykNCnJlcXVpcmUoY2FyKQ0KcmVxdWlyZShzdXJ2ZXkpDQpyZXF1aXJlKHJlYWRyKQ0KYGBgDQoNClRoZSBmb2xsb3dpbmcgc2hvd3MgdGhlIGNvbHVtbnMgd2UgaW1wb3J0ZWQuDQpgYGB7ciAsbWVzc2FnZT1GQUxTRSwgZWNobyA9IEZBTFNFfQ0KYXR0YWNoKHNzMTRwdXNhKQ0KI25hbWVzKHNzMTRwdXNhKQ0Kc3MxNHB1c2FfZWRpdCA9IGRhdGEuZnJhbWUoU0VYLE9DQ1AsV0tIUCxNQVIsV0FHUCxTQ0hMLEVTUCwgUkFDMVAsIFNULCBQQU9DLCBQV0dUUCwgQUdFUCkNCmRldGFjaChzczE0cHVzYSkNCg0KYXR0YWNoKHNzMTRwdXNiKQ0Kc3MxNHB1c2JfZWRpdCA9IGRhdGEuZnJhbWUoU0VYLE9DQ1AsV0tIUCxNQVIsV0FHUCxTQ0hMLEVTUCwgUkFDMVAsIFNULCBQQU9DLCBQV0dUUCwgQUdFUCkNCmRldGFjaChzczE0cHVzYikNCg0KRGF0YSA9IHJiaW5kKHNzMTRwdXNhX2VkaXQsc3MxNHB1c2JfZWRpdCkNCmNvbG5hbWVzKERhdGEpIDwtIGMoIkdlbmRlciIsIk9jY3VwYXRpb24iLCAiV29ya19ob3VycyIsICJNYXJyaWFnZSIsICJJbmNvbWUiLCAiRWR1Y2F0aW9uIiAsIlBhcmVudGFsX09jY3VwYXRpb24iLCAiUmFjZSIsICJTdGF0ZSIsICJDaGlsZHJlbiIsICJXZWlnaHQiLCJBZ2UiKQ0KDQojd3JpdGUuY3N2KERhdGEsIGZpbGUgPSAiRGF0YS5jc3YiLHJvdy5uYW1lcz1UUlVFKQ0KDQojRGVsZXRlIGluY29tZT0wL05BIHJvd3MNCnJvd190b19rZWVwPXdoaWNoKERhdGEkSW5jb21lPjApDQpEYXRhPURhdGFbcm93X3RvX2tlZXAsXQ0KYGBgDQpXZSByZW5hbWVkIGFuZCBjYXRlZ29yaXplZCBtdWx0aXBsZSBjYXRlZ29yaWVzIGZvciByZWFkYWJsaWx0eS4NCg0KTm90ZTogd2UgdXNlZCBlaWdodCBoaWdoIHBheWluZyBvY2N1cGF0aW9uIHRvIGNhdGVnb3JpemUgam9icw0KYGBge3IsZWNobz1GQUxTRSxtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmdzID0gRkFMU0V9DQojcmVjb2RlIE9DQ1ANCmNsYXNzKERhdGEkT2NjdXBhdGlvbikgPC0gIm51bWVyaWMiDQpEYXRhJE9jY3VwYXRpb24gPC0gaWZlbHNlKERhdGEkT2NjdXBhdGlvbiA+PSAxMCAmIERhdGEkT2NjdXBhdGlvbiA8PSA0MzAsIDEsIERhdGEkT2NjdXBhdGlvbikNCkRhdGEkT2NjdXBhdGlvbiA8LSBpZmVsc2UoRGF0YSRPY2N1cGF0aW9uID49IDEwMDUgJiBEYXRhJE9jY3VwYXRpb24gPD0gMTI0MCwgMiwgRGF0YSRPY2N1cGF0aW9uKQ0KRGF0YSRPY2N1cGF0aW9uIDwtIGlmZWxzZShEYXRhJE9jY3VwYXRpb24gPj0gODAwICYgRGF0YSRPY2N1cGF0aW9uIDw9IDk1MCwgMywgRGF0YSRPY2N1cGF0aW9uKQ0KRGF0YSRPY2N1cGF0aW9uIDwtIGlmZWxzZShEYXRhJE9jY3VwYXRpb24gPj0gMjEwNSAmIERhdGEkT2NjdXBhdGlvbiA8PSAyMTYwLCA0LCBEYXRhJE9jY3VwYXRpb24pDQpEYXRhJE9jY3VwYXRpb24gPC0gaWZlbHNlKERhdGEkT2NjdXBhdGlvbiA+PSAzMDAwICYgRGF0YSRPY2N1cGF0aW9uIDw9IDM1NDAsIDUsIERhdGEkT2NjdXBhdGlvbikNCkRhdGEkT2NjdXBhdGlvbiA8LSBpZmVsc2UoRGF0YSRPY2N1cGF0aW9uID49IDUxMCAmIERhdGEkT2NjdXBhdGlvbiA8PSA3NDAsIDYsIERhdGEkT2NjdXBhdGlvbikNCkRhdGEkT2NjdXBhdGlvbiA8LSBpZmVsc2UoRGF0YSRPY2N1cGF0aW9uID49IDEzMDAgJiBEYXRhJE9jY3VwYXRpb24gPD0gMTU2MCwgNywgRGF0YSRPY2N1cGF0aW9uKQ0KRGF0YSRPY2N1cGF0aW9uIDwtIGlmZWxzZShEYXRhJE9jY3VwYXRpb24gPj0gMTYwMCAmIERhdGEkT2NjdXBhdGlvbiA8PSAxOTY1LCA4LCBEYXRhJE9jY3VwYXRpb24pDQoNCnJvd190b19rZWVwMj13aGljaChEYXRhJE9jY3VwYXRpb24laW4lIGMoMTo4KSkNCkRhdGEgPC0gRGF0YVtyb3dfdG9fa2VlcDIsXQ0KRGF0YSRPY2N1cGF0aW9uIDwtIGFzLmZhY3RvcihEYXRhJE9jY3VwYXRpb24pDQoNCmxldmVscyhEYXRhJE9jY3VwYXRpb24pIDwtIGMoJ01HUicsICdDTU0nLCAnRklOJywgJ0xHTCcsICdNRUQnICwgJ0JVUycsICdFTkcnLCAnU0NJJykNCkRhdGEkUmFjZSA8LSBhcy5mYWN0b3IoRGF0YSRSYWNlKQ0KbGV2ZWxzKERhdGEkUmFjZSkgPC0gYygnV2hpdGUnLCAnQmxhY2snLCAnQW1lcmljYW4gSW5kaWFuJywnQWxhc2thIE5hdGl2ZScsJ1RyaWJlIHNwZWNpZmllZCcsICdBc2lhbicgLCAnTmF0aXZlIEhhd2FpaWFuJywgJ090aGVyJywnVHdvIG9yIG1vcmUgcmFjZXMnKQ0KDQojUmVjb2RlIE1hcnJpYWdlDQpEYXRhJE1hcnJpYWdlIDwtIGFzLmZhY3RvcihEYXRhJE1hcnJpYWdlKQ0KbGV2ZWxzKERhdGEkTWFycmlhZ2UpIDwtIGMoIk1hcnJpZWQiLCAiV2lkb3dlZCIsICJEaXZvcmNlZCIsICJTZXBlcmF0ZWQiLCAiTmV2ZXIgTWFycmllZCIpDQoNCiMgUmVjb2RlIEVkdWNhdGlvbg0KRGF0YSRFZHVjYXRpb24gPC0gcmVjb2RlKERhdGEkRWR1Y2F0aW9uLCIxOjExPScxJzsxMjoxOT0nMic7MjA6MjE9JzMnOzIyOjIzPSc0JzsyND0nNSciKQ0KDQpjb2xuYW1lcyhEYXRhKSA8LSBjKCJHZW5kZXIiLCJPY2N1cGF0aW9uIiwgIldvcmtfaG91cnMiLCAiTWFycmlhZ2UiLCAiSW5jb21lIiwgIkVkdWNhdGlvbiIgLCJQYXJlbnRhbF9PY2N1cGF0aW9uIiwgIlJhY2UiLCAiU3RhdGUiLCAiQ2hpbGRyZW4iLCAiV2VpZ2h0IiwiQWdlIikNCg0KVGVtcCA8LSBEYXRhDQpgYGANCkJhc2VkIG9uIHRoZSBlaWdodCBvY2N1cGF0aW9ucywgd2UgcGxvdCB0aGUgd2VpZ2h0ZWQgbWVhbiBvZiBtZW4gYW5kIHdvbWVuIHRvIGNvbXBhcmUgdGhlIGdhcC4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiNtZWRpYW4gd2FnZSBmb3IgZWFjaCBvY2N1cGF0aW9uIGJ5IGdlbmRlciAoanVzdCB0byBhY2tub3dsZWRnZSB0aGF0IHRoZXJlICppcyogYSBnZW5kZXIgZ2FwKQ0KDQpEYXRhX3NleF9vY2NwIDwtIGRkcGx5KERhdGEsIC4oR2VuZGVyLCBPY2N1cGF0aW9uKSwgc3VtbWFyaXNlLCBNRUFOID0gd2VpZ2h0ZWQubWVhbihJbmNvbWUsIFdlaWdodCwgbmEucm0gPSBUKSkNCmdncGxvdChEYXRhX3NleF9vY2NwLCBhZXMoeD1PY2N1cGF0aW9uLCB5PU1FQU4sIGZpbGw9ZmFjdG9yKEdlbmRlcikpKSArIA0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb249ImRvZGdlIikgKyANCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iUmRZbEduIikgKw0KICBsYWJzKGZpbGw9IiIpICsgDQogIHlsYWIoIk1lYW4gU2FsYXJ5ICgkKSIpICsgDQogIHhsYWIoIk9jY3VwYXRpb25zIikgKyANCiAgZ2d0aXRsZShwYXN0ZSgiU2FsYXJ5IENvbXBhcmlzb24gYmV0d2VlbiBNZW4gJiBXb21lbiIpKSArIA0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLCBoanVzdCA9IDEpLCANCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gJ3doaXRlJyApKSArIA0KICB0aGVtZV9ncmV5KGJhc2Vfc2l6ZSA9IDEyKQ0KYGBgDQoNCkZyb20gdGhlIGdyYXBoLCB3ZSBzZWUgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gbWVuIGFuZCB3b21lbiBvdmVyIGFsbCBvY2N1cGF0aW9ucy4gVG8gZ2FpbiBhIGJldHRlciB1bmRlcnN0YW5kaW5nIHdlIGdyYXBoZWQgdGhlbSBieSBwZXJjZW50YWdlIGZyb20gdGhlIHdlaWdodGVkIG1lYW4gb2YgYm90aCBnZW5kZXJzLg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRX0NCkRhdGFfc2V4X29jY3BfcmFjZSA8LSBkZHBseShEYXRhLCAuKEdlbmRlciwgT2NjdXBhdGlvbiwgUmFjZSksIHN1bW1hcmlzZSwgTUVBTiA9IHdlaWdodGVkLm1lYW4oSW5jb21lLCBXZWlnaHQsIG5hLnJtID0gVCkpDQpEYXRhX3NleF9vY2NwX3JhY2Vfd29tZW4gPC0gRGF0YV9zZXhfb2NjcF9yYWNlW3doaWNoKERhdGFfc2V4X29jY3BfcmFjZSRHZW5kZXIgPT0gMiksXQ0KRGF0YV9zZXhfb2NjcF9tZW4gPC0gRGF0YV9zZXhfb2NjcFt3aGljaChEYXRhX3NleF9vY2NwJEdlbmRlciA9PSAxKSxdDQpEYXRhX3NleF9vY2NwX3dvbWVuIDwtIERhdGFfc2V4X29jY3Bbd2hpY2goRGF0YV9zZXhfb2NjcCRHZW5kZXIgPT0gMiksXQ0KDQojR2V0dGluZyB0aGUgYXZlcmFnZSBmb3IgYm90aCBnZW5kZXINCkRhdGFfb2NjdSA8LSBkZHBseShEYXRhLCAuKE9jY3VwYXRpb24pLHN1bW1hcmlzZSxNRUFOID0gd2VpZ2h0ZWQubWVhbihJbmNvbWUsIFdlaWdodCwgbmEucm0gPSBUKSkNCkRhdGFfc2V4X29jY3BfbWVhbiA8LSBkYXRhLmZyYW1lKERhdGFfc2V4X29jY3Bfd29tZW4kT2NjdXBhdGlvbixEYXRhX3NleF9vY2NwX21lbiRNRUFOLERhdGFfc2V4X29jY3Bfd29tZW4kTUVBTiwgRGF0YV9vY2N1JE1FQU4pDQpjb2xuYW1lcyhEYXRhX3NleF9vY2NwX21lYW4pIDwtIGMoJ09jY3VwYXRpb24nLCdNZW4nLCdXb21lbicsJ0F2ZXJhZ2UnKQ0KDQojQ2hhbmdlcyBhbGwgdG8gcGVyY2VudGFnZQ0KRGF0YV9zZXhfb2NjcF9tZWFuX3BlcmNlbnQgPC0gZGF0YS5mcmFtZShEYXRhX3NleF9vY2NwX3dvbWVuJE9jY3VwYXRpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEwMCooRGF0YV9zZXhfb2NjcF9tZW4kTUVBTi1EYXRhX29jY3UkTUVBTikvRGF0YV9vY2N1JE1FQU4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEwMCooRGF0YV9zZXhfb2NjcF93b21lbiRNRUFOLURhdGFfb2NjdSRNRUFOKS9EYXRhX29jY3UkTUVBTikNCmNvbG5hbWVzKERhdGFfc2V4X29jY3BfbWVhbl9wZXJjZW50KSA8LSBjKCdPY2N1cGF0aW9uJywnTWVuJywnV29tZW4nKQ0KDQpwbG90X2x5KERhdGFfc2V4X29jY3BfbWVhbl9wZXJjZW50LCB4ID0gV29tZW4sIHkgPSBPY2N1cGF0aW9uLCBuYW1lID0gIldvbWVuIiwgbW9kZSA9ICJtYXJrZXJzIiwgbWFya2VyID0gbGlzdChjb2xvciA9ICJyZWQiKSkgJT4lDQogIGFkZF90cmFjZSh4ID0gTWVuLCBuYW1lID0gIk1lbiIsIHkgPSBPY2N1cGF0aW9uLCBtYXJrZXIgPSBsaXN0KGNvbG9yID0gImJsdWUiKSwgbW9kZSA9ICJtYXJrZXJzIikgJT4lDQogIGxheW91dCh0aXRsZSA9ICJHZW5kZXIgZWFybmluZ3MgZGlzcGFyaXR5IGJ5IFBlcmNlbnRhZ2UiLHhheGlzID0gbGlzdCh0aXRsZSA9ICJQZXJjZW50IENoYW5nZSAoJSkiKSxtYXJnaW4gPSBsaXN0KGwgPSA2NSkpDQoNCmBgYA0KT2JlcnNlcnZhdGlvbnM6DQoNCjEuIE1lZGljYWwgb2NjdXBhdGlvbnMgaGFzIHRoZSBsYXJnZXN0IGRpc3Blcml0eSBiZXR3ZWVuIG1lbiBhbmQgd29tZW4NCg0KMi4gV29tZW4gaW4gbGVnYWwgb2NjdXBhdGlvbnMgYXJlIHRoZSBjbG9zZXN0IHRvIHRoZSBtZWRpYW4gDQoNCkluIHRoaXMgcmVwb3J0LCB3ZSB3aWxsIGludmVzdGlnYXRlIDUgcHJvYmFibGUgY2F1c2VzIHRvIGRldGVybWluZSB3aGljaCBncm91cHMgb2Ygd29tZW4gd2lsbCBtb3N0IGxpa2VseSBzdWNjZWVkIG9yIGZhaWwuIFRoZXNlIGNhdGVnb3JpZXMgYXJlOiBNYXJyaWFnZSBTdGF0dXMsIE1vdGhlcmhvb2QsIExvY2F0aW9uLCBSYWNlLCBhbmQgRWR1Y2F0aW9uLiAgDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCg0KdCA8LXBhc3RlKCIgIikNCmBgYA0KDQojRmFtaWxpYWwgUmVzcG9uc2liaWxpdGllcw0KDQpPdXIgbmV4dCB2YXJpYWJsZSBvZiBpbnRlcmVzdCBpcyB3b21lbidzIG1hcml0YWwgc3RhdHVzZXMuIEEgY29tbW9uIGV4cGxhbmF0aW9uIG9mIHRoZSBnZW5kZXIgd2FnZSBnYXAgaXMgdGhhdCB3b21lbiBtYWtlIHRoZSBkZWNpc2lvbiB3aXRoIHRoZWlyIGZhbWlsaWVzIHRvIHNoaWZ0IHRoZWlyIGZvY3VzIHRvIGhvdXNlaG9sZCByZXNwb25zaWJpbGl0aWVzLiBXZSdsbCBiZSBsb29raW5nIGF0IHRoZSBlZmZlY3Qgb2YgbWFycmlhZ2UgYW5kIG1vdGhlcmhvb2Qgc2VwZXJhdGVseSBmaXJzdCwgdGhlbiBsb29raW5nIGhvdyBtYXJpdGFsIHN0YXR1c2VzIG9mIG1vdGhlcnMgYWZmZWN0IHRoZWlyIGVhcm5pbmdzLg0KDQojI01hcml0YWwgU3RhdHVzDQpCZWxvdyB3ZSBhbmFseXNlIHRoZSBlZmZlY3Qgb2YgbWFyaXRhbCBzdGF0dXMgb24gbWVhbiBpbmNvbWUgZm9yIHdvbWVuIGFjcm9zcyBhbGwgb2NjdXBhdGlvbnMsIGFzIHdlbGwgYXMgd2l0aGluIG9jY3VwYXRpb25zLg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCg0KI21hcml0YWwgc3RhdHVzLCBzdWJzZXQgYXQgc3BlY2lmaWMgYWdlIHRvIGNvbnRyb2wgZm9yIGV4cGVyaWVuY2UNCkRhdGFfd29tZW4gPC0gZmlsdGVyKERhdGEsIEdlbmRlciA9PSAyKQ0KRGF0YV93ZWRfb2NjcCA8LSBkZHBseShEYXRhX3dvbWVuLCAuKE1hcnJpYWdlLCBPY2N1cGF0aW9uLCBBZ2UpLCBzdW1tYXJpc2UsIE1FQU4gPSB3ZWlnaHRlZC5tZWFuKEluY29tZSwgV2VpZ2h0LCBuYS5ybSA9IFQpKQ0KDQpzdW1tYXJ5KGxtKE1FQU4gfiBNYXJyaWFnZSArIEFnZSArIEkoQWdlXjIpICwgZGF0YSA9IERhdGFfd2VkX29jY3ApKQ0KYGBgDQpgYGB7ciBlY2hvID1GQUxTRX0NCiNGaW5hbmNlDQpXb21lbl9GSU48LWZpbHRlcihEYXRhX3dvbWVuLCBPY2N1cGF0aW9uID09IkZJTiIpDQpEYXRhX3dlZF9GSU4gPC0gZGRwbHkoV29tZW5fRklOLCAuKE1hcnJpYWdlLCBBZ2UpLCBzdW1tYXJpc2UsIE1FQU4gPSB3ZWlnaHRlZC5tZWFuKEluY29tZSwgV2VpZ2h0LCBuYS5ybSA9IFQpKQ0KDQpGSU4gPC0gcGxvdF9seShEYXRhX3dlZF9GSU4sIHggPSBBZ2UsIHkgPSBNRUFOLCBtb2RlID0gIm1hcmtlcnMiLCBvcGFjaXR5ID0gLjQsIGNvbG9yID0gTWFycmlhZ2UsIHRpdGxlID0gIldvbWVuIGluIEZpbmFuY2UiKSANCkZJTiA8LWFkZF90cmFjZShGSU4seSA9IGZpdHRlZChsb2VzcyhNRUFOIH4gQWdlICsgYXMubnVtZXJpYyhNYXJyaWFnZSkpKSAsIHggPSBBZ2UsIGNvbG9yID0gTWFycmlhZ2UpIA0KbGF5b3V0KEZJTiwgdGl0bGUgPSAiV29tZW4gaW4gRmluYW5jZSIpDQoNCnN1bW1hcnkobG0oTUVBTiB+IE1hcnJpYWdlICsgQWdlICsgSShBZ2VeMiksIGRhdGEgPSBEYXRhX3dlZF9GSU4pKQ0KYGBgDQpgYGB7ciBlY2hvID1GQUxTRX0NCiNFbmdpbmVlcmluZw0KDQpXb21lbl9FTkc8LWZpbHRlcihEYXRhX3dvbWVuLCBPY2N1cGF0aW9uID09IkVORyIpDQpEYXRhX3dlZF9FTkcgPC0gZGRwbHkoV29tZW5fRU5HLCAuKE1hcnJpYWdlLCBBZ2UpLCBzdW1tYXJpc2UsIE1FQU4gPSB3ZWlnaHRlZC5tZWFuKEluY29tZSwgV2VpZ2h0LCBuYS5ybSA9IFQpKQ0KDQojcGxvdGx5DQpFTkcgPC0gcGxvdF9seShEYXRhX3dlZF9FTkcsIHggPSBBZ2UsIHkgPSBNRUFOLCBtb2RlID0gIm1hcmtlcnMiLCBvcGFjaXR5ID0gLjQsIGNvbG9yID0gTWFycmlhZ2UsIHRpdGxlID0gIldvbWVuIGluIEZpbmFuY2UiKSANCkVORyA8LWFkZF90cmFjZShFTkcseSA9IGZpdHRlZChsb2VzcyhNRUFOIH4gQWdlICsgYXMubnVtZXJpYyhNYXJyaWFnZSkpKSAsIHggPSBBZ2UsIGNvbG9yID0gTWFycmlhZ2UpIA0KbGF5b3V0KEVORywgdGl0bGUgPSAiV29tZW4gaW4gRW5naW5lZXJpbmciKQ0KDQpsbTEgPC0gbG0oTUVBTiB+IE1hcnJpYWdlICsgQWdlICsgSShBZ2VeMiksIGRhdGEgPSBEYXRhX3dlZF9FTkcpDQpzdW1tYXJ5KGxtMSkNCmBgYA0KYGBge3IgZWNobyA9RkFMU0V9DQojTWVkaWNpbmUNCg0KV29tZW5fTUVEPC1maWx0ZXIoRGF0YV93b21lbiwgT2NjdXBhdGlvbiA9PSJNRUQiKQ0KRGF0YV93ZWRfTUVEIDwtIGRkcGx5KFdvbWVuX01FRCwgLihNYXJyaWFnZSwgQWdlKSwgc3VtbWFyaXNlLCBNRUFOID0gd2VpZ2h0ZWQubWVhbihJbmNvbWUsIFdlaWdodCwgbmEucm0gPSBUKSkNCg0KI3Bsb3RseQ0KTUVEIDwtIHBsb3RfbHkoRGF0YV93ZWRfTUVELCB4ID0gQWdlLCB5ID0gTUVBTiwgbW9kZSA9ICJtYXJrZXJzIiwgb3BhY2l0eSA9IC40LCBjb2xvciA9IE1hcnJpYWdlLCB0aXRsZSA9ICJXb21lbiBpbiBGaW5hbmNlIikgDQpNRUQgPC1hZGRfdHJhY2UoTUVELHkgPSBmaXR0ZWQobG9lc3MoTUVBTiB+IEFnZSArIGFzLm51bWVyaWMoTWFycmlhZ2UpKSkgLCB4ID0gQWdlLCBjb2xvciA9IE1hcnJpYWdlKSANCmxheW91dChNRUQsIHRpdGxlID0gIldvbWVuIGluIEZpbmFuY2UiKQ0KDQoNCnN1bW1hcnkobG0oTUVBTiB+IE1hcnJpYWdlICsgQWdlICsgSShBZ2VeMiksIGRhdGEgPSBEYXRhX3dlZF9NRUQpKQ0KYGBgDQpgYGB7ciBlY2hvID1GQUxTRX0NCiNTY2llbmNlDQoNCldvbWVuX1NDSTwtZmlsdGVyKERhdGFfd29tZW4sIE9jY3VwYXRpb24gPT0iU0NJIikNCkRhdGFfd2VkX1NDSSA8LSBkZHBseShXb21lbl9TQ0ksIC4oTWFycmlhZ2UsIEFnZSksIHN1bW1hcmlzZSwgTUVBTiA9IHdlaWdodGVkLm1lYW4oSW5jb21lLCBXZWlnaHQsIG5hLnJtID0gVCkpDQoNCiNwbG90bHkNClNDSSA8LSBwbG90X2x5KERhdGFfd2VkX1NDSSwgeCA9IEFnZSwgeSA9IE1FQU4sIG1vZGUgPSAibWFya2VycyIsIG9wYWNpdHkgPSAuNCwgY29sb3IgPSBNYXJyaWFnZSwgdGl0bGUgPSAiV29tZW4gaW4gU2NpZW5jZSIpIA0KU0NJIDwtYWRkX3RyYWNlKFNDSSx5ID0gZml0dGVkKGxvZXNzKE1FQU4gfiBBZ2UgKyBhcy5udW1lcmljKE1hcnJpYWdlKSkpICwgeCA9IEFnZSwgY29sb3IgPSBNYXJyaWFnZSkgDQpsYXlvdXQoU0NJLCB0aXRsZSA9ICJXb21lbiBpbiBTY2llbmNlIikNCg0KDQpzdW1tYXJ5KGxtKE1FQU4gfiBNYXJyaWFnZSArIEFnZSArIEkoQWdlXjIpLCBkYXRhID0gRGF0YV93ZWRfU0NJKSkNCmBgYA0KYGBge3IgZWNobyA9RkFMU0V9DQojTWFuYWdlcnMNCldvbWVuX01HUjwtZmlsdGVyKERhdGFfd29tZW4sIE9jY3VwYXRpb24gPT0iTUdSIikNCkRhdGFfd2VkX01HUiA8LSBkZHBseShXb21lbl9NR1IsIC4oTWFycmlhZ2UsIEFnZSksIHN1bW1hcmlzZSwgTUVBTiA9IHdlaWdodGVkLm1lYW4oSW5jb21lLCBXZWlnaHQsIG5hLnJtID0gVCkpDQoNCk1HUiA8LSBwbG90X2x5KERhdGFfd2VkX01HUiwgeCA9IEFnZSwgeSA9IE1FQU4sIG1vZGUgPSAibWFya2VycyIsIG9wYWNpdHkgPSAuNCwgY29sb3IgPSBNYXJyaWFnZSwgdGl0bGUgPSAiV29tZW4gaW4gTWFuYWdlbWVudCIpIA0KTUdSIDwtYWRkX3RyYWNlKE1HUix5ID0gZml0dGVkKGxvZXNzKE1FQU4gfiBBZ2UgKyBhcy5udW1lcmljKE1hcnJpYWdlKSkpICwgeCA9IEFnZSwgY29sb3IgPSBNYXJyaWFnZSkgDQpsYXlvdXQoTUdSLCB0aXRsZSA9ICJXb21lbiBpbiBNYW5hZ2VtZW50IikNCg0Kc3VtbWFyeShsbShNRUFOIH4gTWFycmlhZ2UgKyBBZ2UgKyBJKEFnZV4yKSwgZGF0YSA9IERhdGFfd2VkX01HUikpDQpgYGANCmBgYHtyIGVjaG8gPUZBTFNFfQ0KDQojTGF3eWVycw0KV29tZW5fTEdMPC1maWx0ZXIoRGF0YV93b21lbiwgT2NjdXBhdGlvbiA9PSJMR0wiKQ0KRGF0YV93ZWRfTEdMIDwtIGRkcGx5KFdvbWVuX0xHTCwgLihNYXJyaWFnZSwgQWdlKSwgc3VtbWFyaXNlLCBNRUFOID0gd2VpZ2h0ZWQubWVhbihJbmNvbWUsIFdlaWdodCwgbmEucm0gPSBUKSkNCg0KTEdMIDwtIHBsb3RfbHkoRGF0YV93ZWRfTEdMLCB4ID0gQWdlLCB5ID0gTUVBTiwgbW9kZSA9ICJtYXJrZXJzIiwgb3BhY2l0eSA9IC40LCBjb2xvciA9IE1hcnJpYWdlKSANCkxHTCA8LWFkZF90cmFjZShMR0wseSA9IGZpdHRlZChsb2VzcyhNRUFOIH4gQWdlICsgYXMubnVtZXJpYyhNYXJyaWFnZSkpKSAsIHggPSBBZ2UsIGNvbG9yID0gTWFycmlhZ2UpIA0KbGF5b3V0KExHTCwgdGl0bGUgPSAiV29tZW4gaW4gTGF3IikNCg0Kc3VtbWFyeShsbShNRUFOIH4gTWFycmlhZ2UgKyBBZ2UgKyBJKEFnZV4yKSwgZGF0YSA9IERhdGFfd2VkX0xHTCkpDQoNCmBgYA0KYGBge3IgZWNobyA9RkFMU0V9DQojQnVzaW5lc3MNCg0KV29tZW5fQlVTPC1maWx0ZXIoRGF0YV93b21lbiwgT2NjdXBhdGlvbiA9PSJCVVMiKQ0KRGF0YV93ZWRfQlVTIDwtIGRkcGx5KFdvbWVuX0JVUywgLihNYXJyaWFnZSwgQWdlKSwgc3VtbWFyaXNlLCBNRUFOID0gd2VpZ2h0ZWQubWVhbihJbmNvbWUsIFdlaWdodCwgbmEucm0gPSBUKSkNCg0KQlVTIDwtIHBsb3RfbHkoRGF0YV93ZWRfQlVTLCB4ID0gQWdlLCB5ID0gTUVBTiwgbW9kZSA9ICJtYXJrZXJzIiwgb3BhY2l0eSA9IC40LCBjb2xvciA9IE1hcnJpYWdlKSANCkJVUyA8LWFkZF90cmFjZShCVVMseSA9IGZpdHRlZChsb2VzcyhNRUFOIH4gQWdlICsgYXMubnVtZXJpYyhNYXJyaWFnZSkpKSAsIHggPSBBZ2UsIGNvbG9yID0gTWFycmlhZ2UpIA0KbGF5b3V0KEJVUywgdGl0bGUgPSAiV29tZW4gaW4gQnVzaW5lc3MiKQ0KDQpzdW1tYXJ5KGxtKE1FQU4gfiBNYXJyaWFnZSArIEFnZSArIEkoQWdlXjIpLCBkYXRhID0gRGF0YV93ZWRfQlVTKSkNCmBgYA0KYGBge3IgZWNobyA9RkFMU0V9DQojQ29tcHV0ZXINCg0KV29tZW5fQ01NPC1maWx0ZXIoRGF0YV93b21lbiwgT2NjdXBhdGlvbiA9PSJDTU0iKQ0KRGF0YV93ZWRfQ01NIDwtIGRkcGx5KFdvbWVuX0NNTSwgLihNYXJyaWFnZSwgQWdlKSwgc3VtbWFyaXNlLCBNRUFOID0gd2VpZ2h0ZWQubWVhbihJbmNvbWUsIFdlaWdodCwgbmEucm0gPSBUKSkNCg0KQ01NIDwtIHBsb3RfbHkoRGF0YV93ZWRfQ01NLCB4ID0gQWdlLCB5ID0gTUVBTiwgbW9kZSA9ICJtYXJrZXJzIiwgb3BhY2l0eSA9IC40LCBjb2xvciA9IE1hcnJpYWdlKSANCkNNTSA8LWFkZF90cmFjZShDTU0seSA9IGZpdHRlZChsb2VzcyhNRUFOIH4gQWdlICsgYXMubnVtZXJpYyhNYXJyaWFnZSkpKSAsIHggPSBBZ2UsIGNvbG9yID0gTWFycmlhZ2UpIA0KbGF5b3V0KENNTSwgdGl0bGUgPSAiV29tZW4gaW4gQ29tcHV0ZXIgU2NpZW5jZSIpDQoNCnN1bW1hcnkobG0oTUVBTiB+IE1hcnJpYWdlICsgQWdlICsgSShBZ2VeMiksIGRhdGEgPSBEYXRhX3dlZF9DTU0pKQ0KDQpgYGAgDQpPYnNlcnZhdGlvbnM6DQoNCjEuIE92ZXJhbGwsd2lkb3dlZCBhbmQgc2VwZXJhdGVkIHdvbWVuIG1ha2Ugc2lnbmlmaWNhbnRseSBsZXNzIHRoYW4gbWFycmllZCB3b21lbiB3aGVuIG9jY3VwYXRpb25zIGFyZSBwb29sZWQuDQoNCjIuIE1hcml0YWwgc3RhdHVzIGhhcyBubyBlZmZlY3Qgb24gZWFybmluZyBmb3Igd29tZW4gaW4gdGhlIHNjaWVudGlmaWMgZmllbGQNCg0KMy4gSW50ZXJlc3RpbmdseSwgZm9yIG1vc3Qgb2NjdXBhdGlvbnMgd2hlcmUgbWFyaXRhbCBzdGF0dXMgaXMgc2lnbmlmaWNhbnQsIHdvbWVuIGluIHRoZWlyIHByb2Zlc3Npb24gd2hvIGhhdmUgbmV2ZXIgYmVlbiBtYXJyaWVkIGVhcm4gbW9yZSB0aGFuIG1hcnJpZWQgd29tZW4sIHdoZXJlYXMgd2lkb3dlZCBhbmQgc2VwZXJhdGVkIHdvbWVuIGVhcm4gc2lnbmlmaWNhbnRseSBsZXNzLiBQZXJoYXBzIHdpZG93ZWQgb3Igc2VwZXJhdGVkIHdvbWVuIGFyZSBtb3JlIGxpa2VseSB0byBoYXZlIGNoaWxkcmVuIHRoYW4gbmV2ZXIgbWFycmllZCB3b21lbiwgYW5kIHRodXMgbXVzdCBzaG91bGRlciBtb3JlIHJlc3BvbnNpYmlsaXRpZXMgb3V0c2lkZSBvZiB3b3JrLg0KDQoNCiNNb3RoZXJob29kDQoNCkFmdGVyIGludmVzdGlnYXRpbmcgaG93IG1hcnJpYWdlIHN0YXR1cyBhZmZlY3Qgd29tZW4ncyBpbmNvbWUsIHdlIGxvb2tlZCBpbnRvIHRoZSBwcmVzZW5jZSBhbmQgYWdlIG9mIGNoaWxkcmVuIG93bmVkIGJ5IHRoZSB3b21lbiB0byBkZXRlcm1pbmUgaG93IGl0IG1pZ2h0IGNvcnJlbGF0ZSB0byB3b21lbidzIGluY29tZS4gV2UgZXhwZWN0IHdvbWVuIHdpdGggQ2hpbGRyZW4gdW5kZXIgNiBtYXkgaGF2ZSBsZXNzIHdvcmtpbmcgaG91cnMgYW5kIHRodXMgbG93ZXIgaW5jb21lIChyZWFzb25pbmc6IHdoZW4gYSBjaGlsZCBpcyB5b3VuZyB0aGUgd29tZW4gb2YgdGhlIGhvdXNlIGlzIG1vcmUgbGlrZWx5IHRvIHN0YXkgaG9tZSB3aXRoIHRoZWlyIGNoaWxkcmVuLiBBcyB3ZSBzZWUgdGhlIGNoaWxkcmVuIGdyb3csIHdlIGV4cGVjdCBhIHRyZW5kIGZvciB3b21lbiB0byBlYXJuIHRoZSBoaWdoZXIuKSBGdXJ0aGVybW9yZSwgd2UgbWF5IGFsc28gd2FudCB0byBmaWd1cmUgb3V0IGhvdyBvY2N1cGF0aW9uIGFuZCBhZ2UgZm9yIHdvbWVuIHdpdGggY2hpbGRyZW4gYWZmZWN0IHRoZWlyIGluY29tZS4NCg0KDQpBdCBmaXJzdCwgd2Ugd2FudCB0byBoYXZlIGEgZ2xhbmNlIGF0IHRoZSBpbmNvbWUgbGV2ZWwgb2YgdGhlIGRpZmZlcmVudCBncm91cHMgb2YgZmVtYWxlcy4gQmFzaWNhbGx5IGZlbWFsZXMgYXJlIGRpdmlkZWQgaW50byBmb3VyIGNhdGVnb3JpZXMgcmVnYXJkaW5nIHRoZSBwcmVzZW5jZSBhbmQgYWdlIG9mIENoaWxkcmVuOiBGZW1hbGVzIHdpdGggQ2hpbGRyZW4gdW5kZXIgNiwgRmVtYWxlcyB3aXRoIENoaWxkcmVuIGZyb20gNiB0byAxNywgRmVtYWxlcyB3aXRoIENoaWxkcmVuIHVuZGVyIDYgYW5kIGFib3ZlIDYsIEZlbWFsZXMgd2l0aCBObyBDaGlsZHJlbi4gVGh1cyB3ZSBzaW1wbHkgY3JlYXQgYSBiYXIgY2hhcnQgdG8gaWxsdXN0cmF0ZSB0aGUgaW5jb21lIGRpZmZlcmVuY2UuDQoNCmBgYHtyfQ0KDQoNCkRhdGFfd29tZW4gPC0gZmlsdGVyKERhdGEsIEdlbmRlciA9PSAyKQ0KRGF0YV93b21lbiRBZ2Vncm91cCA8LSBjdXQoYXMubnVtZXJpYyhEYXRhX3dvbWVuJEFnZSksIGJyZWFrcyA9IGMoMjAsMjUsMzAsMzUsNDAsNDUsNTAsNTUsNjAsNjUpKQ0KRGF0YV93b21lbiA8LSBmaWx0ZXIoRGF0YV93b21lbiwgQWdlID4gMjAgJiBBZ2UgPCA2NikNCg0KTW90aGVySG9vZD1zZWxlY3QoRGF0YV93b21lbiwgSW5jb21lLENoaWxkcmVuKQ0KZGV0YWNoKHBhY2thZ2U6cGx5cikNCkdyb3VwZWRNb3RoZXJIb29kIDwtDQogIE1vdGhlckhvb2QgJT4lDQogIG5hLm9taXQoKSAlPiUNCiAgZ3JvdXBfYnkoQ2hpbGRyZW4pICU+JQ0KICBzdW1tYXJpemUoDQogICAgQXZnSW5jb21lID0gbWVhbihJbmNvbWUpDQogICkNCg0KDQoNCg0KR3JvdXBlZE1vdGhlckhvb2QkQ2hpbGRyZW48LWZhY3RvcihHcm91cGVkTW90aGVySG9vZCRDaGlsZHJlbiwgbGV2ZWxzID0gYygiMSIsIjIiLCIzIiwiNCIpLCBjKCdDaGlsZHJlbiB1bmRlciA2JywnQ2hpbGRyZW4gZnJvbSA2IHRvIDE3JywnQ2hpbGRyZW4gdW5kZXIgNiBhbmQgYWJvdmUgNicsJ05vIENoaWxkcmVuJykpDQoNCg0KDQpnZ3Bsb3QoR3JvdXBlZE1vdGhlckhvb2QsIGFlcyh4PUNoaWxkcmVuLCB5PUF2Z0luY29tZSkpICsNCiAgZ2VvbV9iYXIod2lkdGg9LjUsIHN0YXQ9ImlkZW50aXR5IikrDQogIGd1aWRlcyhmaWxsPUZBTFNFKSArDQogIHhsYWIoIk1vdGhlckhvb2QiKSArIHlsYWIoIk1lYW4gSW5jb21lIikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoNTAwMDAsNzAwMDApKSArDQogIGdndGl0bGUoIkluY29tZSBmb3IgTW90aGVyaG9vZCIpDQoNCmBgYA0KDQoNCg0KT2JzZXJ2YXRpb25zOg0KVGhlIGJhciBjaGFydCB2ZXJpZmllcyBvdXIgZ3Vlc3MuIFdvbWVuIHdpdGggY2hpbGRyZW4gNiB0byAxNyBoYXMgb2J2aW91c2x5IGhpZ2hlciBBdmVyYWdlIEluY29tZSBhcyB0aGV5IGhhdmUgbW9yZSB3b3JraW5nIGV4cGVyaWVuY2UgYW5kIGRvIG5vdCBuZWVkIHRvIHNwZW5kIHRvbyBtdWNoIHRpbWUgdG8gdGFrZSBjYXJlIG9mIHlvdW5nIGNoaWxkcmVuLiBPbiB0aGUgb3RoZXIgaGFuZCwgd29tZW4gd2l0aCBDaGlsZHJlbiBvZiBib3RoIGFnZXMgaGF2ZSBzbGlnaHRseSBsb3dlciBpbmNvbWUsIHdoaWNoIGlzIGFsc28gcmVhc29uYWJsZSBhcyB0aGV5IG1heSBub3QgaGF2ZSB0b28gbXVjaCB0aW1lIGluIHdvcmsuDQoNCg0KTmV4dCwgaW4gb3JkZXIgdG8gYmV0dGVyIHVuZGVyc3RhbmQgd2h5IHdvbWVuIHdpdGggY2hpbGRyZW4gNiB0byAxNyBoYXZlIGhpZ2hlciBpbmNvbWUgYW5kIHdoZXRoZXIgaXQgaGFzIGFueXRoaW5nIHRvIGRvIHdpdGggYWdlLCB3ZSBhcmUgZ29pbmcgdG8gc3R1ZHkgaG93IHRoZSBpbmNvbWUgY2hhbmdlIGZvciBkaWZmZXJlbnQgZ3JvdXBzIG9mIHdvbWVuIHRocm91Z2ggb3V0IGFnZS4gQmFzaWNhbGx5IHdlIHRyeSB0byBhbmFseXplIGJ5IGxpbmUgY2hhcnQgdG8gc2VlIHRoZSBpbmNvbWUgdHJlbmQgYW5kIGNvbXBhcmUuDQpgYGB7cn0NCg0KDQpNb3RoZXJIb29kPXNlbGVjdChEYXRhX3dvbWVuLCBJbmNvbWUsQ2hpbGRyZW4sQWdlZ3JvdXApDQojZGV0YWNoKHBhY2thZ2U6cGx5cikNCkdyb3VwZWRNb3RoZXJIb29kIDwtDQogIE1vdGhlckhvb2QgJT4lDQogIG5hLm9taXQoKSAlPiUNCiAgZ3JvdXBfYnkoQ2hpbGRyZW4sQWdlZ3JvdXApICU+JQ0KICBzdW1tYXJpemUoDQogICAgQXZnSW5jb21lID0gbWVhbihJbmNvbWUpDQogICkNCg0KDQojIyMgTGluZSBDaGFydCB3aXRoIHJlZ2FyZCB0byBBZ2UNCg0KR3JvdXBlZE1vdGhlckhvb2QkQ2hpbGRyZW48LWZhY3RvcihHcm91cGVkTW90aGVySG9vZCRDaGlsZHJlbiwgbGV2ZWxzID0gYygiMSIsIjIiLCIzIiwiNCIpLCBjKCdDaGlsZHJlbiB1bmRlciA2JywnQ2hpbGRyZW4gZnJvbSA2IHRvIDE3JywnQ2hpbGRyZW4gdW5kZXIgNiBhbmQgYWJvdmUgNicsJ05vIENoaWxkcmVuJykpDQoNCg0KDQojZ2dwbG90KEdyb3VwZWRNb3RoZXJIb29kLCBhZXMoeD1BZ2Vncm91cCwgeT1BdmdJbmNvbWUsZmlsbD1DaGlsZHJlbikpICsNCiMgIGdlb21fYmFyKHdpZHRoPS41LCBzdGF0PSJpZGVudGl0eSIpKw0KIyAgeGxhYigiQWdlIEdyb3VwIikgKyB5bGFiKCJNZWFuIEluY29tZSIpICsNCiMgIGdndGl0bGUoIkluY29tZSBmb3IgTW90aGVyaG9vZCIpDQoNCg0KZ2dwbG90KEdyb3VwZWRNb3RoZXJIb29kLCBhZXMoeD1BZ2Vncm91cCwgeT1BdmdJbmNvbWUsZ3JvdXA9Q2hpbGRyZW4sY29sb3VyPUNoaWxkcmVuKSkgKw0KICBnZW9tX2xpbmUoKSsNCiAgZ2VvbV9wb2ludCgpKw0KICAjZ3VpZGVzKGZpbGw9RkFMU0UpICsNCiAgeGxhYigiQWdlIEdyb3VwIikgKyB5bGFiKCJNZWFuIEluY29tZSIpICsNCiAgZ2d0aXRsZSgiSW5jb21lIGZvciBNb3RoZXJob29kIikNCg0KDQpgYGANCg0KT2JzZXJ2YXRpb25zOg0KMS4gQmVmb3JlIDQ1LTUwIHllYXJzIG9sZCwgdGhlcmUgaXMgYW4gYWJ2aW91cyBpbmNyZWFzaW5nIHRyZW5kIG9mIGluY29tZSBiYXNpY2FsbHkgZm9yIGFsbCBncm91cHMuIEFuZCBhZnRlciB0aGF0IGFnZSwgYXZlcmFnZSBpbmNvbWUgYmVnaW5zIHRvIGRlY3JlYXNlIG9yIHN0YWJsaXplLg0KMi4gU3VycHJpc2luZ2x5LCBmb3IgdGhlIHNhbWUgYWdlIGdyb3VwLCB3b21lbiB3aXRoIENoaWxkcmVuIHVuZGVyIDYgaGF2ZSBoaWdoZXIgaW5jb21lLiBXaGlsZSB3b21lbiB3aXRoIGNoaWxkcmVuIGZyb20gNiBhbmQgMTcgaGF2ZSBoaWdoZXIgaW5jb21lIGFmdGVyIDQ1IHllYXJzIG9sZCwgd2hpY2ggbWlnaHQgYmUgdGhlIHJlYXNvbiB0aGlzIGdyb3VwIGhhcyBoaWdoZXIgYXZlcmFnZSBpbmNvbWUuIE9uIHRoZSBvdGhlciBoYW5kLCB3b21lbiB3aXRoIG5vIGNoaWxkcmVuIGRvZXNuJ3QgZWFybiBsZXNzIHRoYW4gb3RoZXIgZ3JvdXBzIGF0IHlvdW5nZXIgYWdlIGdyb3VwcywgYnV0IHRoZWlyIGluY29tZSBiZWNvbWUgc3RhYmxlIGFuZCBsZXNzIHRoYW4gb3RoZXJzIGFmdGVyIDQwIHllYXJzIG9sZC4NCg0KDQpOZXh0LCB3ZSB3YW50ZWQgdG8gc2VlIGhvdyB0aGUgd29ya2luZyBob3VycyByZWxhdGVkIHRvIHRoZSBpbmNvbWUgb2Ygd29tZW4gaW4gZGlmZmVyZW50IGdyb3VwLiBXaWxsIHdvbWVuIHdpdGggY2hpbGRyZW4gZnJvbSA2IHRvIDE3IGhhdmUgbW9yZSB3b3JraW5nIGhvdXJzIGFuZCBnZW5lcmF0ZSBoaWdoZXIgaW5jb21lPw0KVGh1cyB3ZSB3YW50IHRvIHVzZSBidWJibGUgY2hhcnQgdG8gaW50ZWdyYXRlIHdvcmtpbmcgaG91cnMsIGF2ZXJhZ2UgaW5jb21lLCB0aGUgZ3JvdXAgY291bnQgaW4gYSBidWJibGUgY2hhcnQgc28gdGhhdCBhbGwgdGhlIGluZm9ybWF0aW9uIGNhbiBiZSBnYWluZWQgaW4gdGhlIHNhbWUgZ3JhcGguDQpgYGB7cn0NCk1vdGhlcldvcmtpbmc9c2VsZWN0KERhdGFfd29tZW4sIEluY29tZSxDaGlsZHJlbixXb3JrX2hvdXJzKQ0KI2RldGFjaChwYWNrYWdlOnBseXIpDQpHcm91cGVkTW90aGVyV29ya2luZyA8LQ0KICBNb3RoZXJXb3JraW5nICU+JQ0KICBuYS5vbWl0KCkgJT4lDQogIGdyb3VwX2J5KENoaWxkcmVuLFdvcmtfaG91cnMpICU+JQ0KICBzdW1tYXJpemUoDQogICAgQXZnSW5jb21lID0gbWVhbihJbmNvbWUpLA0KICAgIGNvdW50PW4oKQ0KICApDQoNCkdyb3VwZWRNb3RoZXJXb3JraW5nJENoaWxkcmVuPC1mYWN0b3IoR3JvdXBlZE1vdGhlcldvcmtpbmckQ2hpbGRyZW4sIGxldmVscyA9IGMoIjEiLCIyIiwiMyIsIjQiKSxsYWJlbHM9IGMoJ0NoaWxkcmVuIHVuZGVyIDYnLCdDaGlsZHJlbiBmcm9tIDYgdG8gMTcnLCdDaGlsZHJlbiB1bmRlciA2IGFuZCBhYm92ZSA2JywnTm8gQ2hpbGRyZW4nKSkNCg0KbGlicmFyeShwbG90bHkpDQojIG5vdGUgaG93IHNpemUgaXMgYXV0b21hdGljYWxseSBzY2FsZWQgYW5kIGFkZGVkIGFzIGhvdmVyIHRleHQNCg0KcGxvdF9seShHcm91cGVkTW90aGVyV29ya2luZywgeCA9IFdvcmtfaG91cnMsIHkgPSBBdmdJbmNvbWUsc2l6ZT1zcXJ0KGNvdW50KSwgY29sb3IgPSBDaGlsZHJlbixtb2RlID0gIm1hcmtlcnMiLGhvdmVyaW5mbyA9ICJ0ZXh0Iix0ZXh0ID0gcGFzdGUoIkF2Z0luY29tZToiLEF2Z0luY29tZSwiPGJyPiIsIkNvdW50OiIsY291bnQsIjxicj4iKSkNCg0KDQoNCmBgYA0KDQoNCk9ic2VydmF0aW9uczoNCjEuIFdoZW4gd29ya19ob3VycyBzbWFsbGVyIHRoYW4gNjBIcnMsIEF2ZyBJbmNvbWUgdGVuZCB0byBiZSBwb3NpdGl2ZWx5IHJlbGF0ZWQgdG8gd29yayBob3VyLCB3aGljaCBhZ3JlZXMgd2l0aCBvdXIgY29tbW9uIGtub3dsZWRnZS4gTW9zdCB3b21lbiBjb25jZW50cmF0ZSBhcm91bmQgNDAgd29ya2luZyBob3Vycy4NCjIuIFRoZXJlIGFyZSBnZW5lcmFsbHkgbW9yZSBmZW1hbGVzIHdpdGggbm8gQ2hpbGRyZW4gaW4gdGhpcyBzdXJ2ZXkgYXMgZ3JlZW4gY2lyY2xlcyBhcmUgZ2VuZXJhbGx5IGxhcmdlciBpbiBzaXplLiBBbHNvIGl0IGNhbiBiZSBvYnNlcnZlZCB0aGVyZSBhcmUgbXVjaCBtb3JlIHdvbWVuIHdpdGggbm8gY2hpbGRyZW4gd29ya2luZyBtb3JlIHRoYW4gNTAgaG91cnMgY29tcGFyZWQgdG8gb3RoZXIgZ3JvdXBzLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlcmUgYXJlIGJhc2ljYWxseSBsZXNzIHdvbWVuIHdpdGggY2hpbGRyZW4gZnJvbSBib3RoIGFnZSBncm91cHMuDQozLiBGZW1hbGVzIHdpdGggQ2hpbGRyZW4gZnJvbSA2IHRvIDE3IG9mdGVuIGhhdmUgaGlnaGVyIGF2ZyBpbmNvbWUuIFdoaWxlIGZvciB0aGUgc2FtZSB3b3JraW5nIGhvdXIgbGV2ZWwsIGZlbWFsZXMgd2l0aCBubyBjaGlsZHJlbiBhcmUgZnJlcXVlbnRseSBoYXZlIGxvd2VyIGF2ZXJhZ2UgaW5jb21lLg0KDQoNCk5leHQgd2Ugd2FudCB0byBpbnZlc3RpZ2F0ZSB3aGV0aGVyIHRoZSBpbmNvbWUgZGlmZmVyZW5jZSBhbW9uZyBmb3VyIGdyb3VvcHMgb2YgZmVtYWxlIGhhdmUgYW55IHJlbGF0aW9uc2hpcCB0byB0aGVpciBvY2N1cGF0aW9uLiBUaGVyZWZvcmUgd2UgdXNlIHRoaXMgY2hhcnQgdG8gY29tcGFyZSB0aGUgaW5jb21lIGZvciBmb3VyIGdyb3VwcyBvZiB3b21lbiBpbiBkaWZmZXJlbnQgb2NjdXBhdGlvbnMuIEJhc2ljYWxseSwgZGFya2VyIGNvbG9yIHJlcHJlc2VudCBoaWdoZXIgaW5jb21lIGFuZCBsYXJnZXIgc2l6ZSBpbmRpY2F0ZSBsYXJnZXIgZ3JvdXAgc2l6ZS4NCmBgYHtyfQ0KTW90aGVyT2NjdXBhdGlvbj1zZWxlY3QoRGF0YV93b21lbiwgSW5jb21lLENoaWxkcmVuLE9jY3VwYXRpb24pDQoNCiNkZXRhY2gocGFja2FnZTpwbHlyKQ0KR3JvdXBlZE1vdGhlck9jY3VwYXRpb24gPC0NCiAgTW90aGVyT2NjdXBhdGlvbiAlPiUNCiAgbmEub21pdCgpICU+JQ0KICBncm91cF9ieShDaGlsZHJlbixPY2N1cGF0aW9uKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIEF2Z0luY29tZSA9IG1lYW4oSW5jb21lKSwNCiAgICBjb3VudD1uKCkNCiAgKQ0KDQoNCg0KZ2dwbG90KEdyb3VwZWRNb3RoZXJPY2N1cGF0aW9uLGFlcyh4PWFzLmZhY3RvcihDaGlsZHJlbikpKStnZW9tX3BvaW50KGFlcyh5PU9jY3VwYXRpb24sc2l6ZT1jb3VudCxjb2xvdXI9QXZnSW5jb21lKSkrZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKEF2Z0luY29tZSkseT1PY2N1cGF0aW9uLG9wYWNpdHk9MCksaGp1c3Q9MCwgdmp1c3Q9MSxzaXplPTIuNSkrc2NhbGVfY29sb3VyX2dyYWRpZW50KGxvdz0id2hpdGUiLGhpZ2g9InJlZCIpK3NjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkNoaWxkcmVuIHVuZGVyIDYiLCAiQ2hpbGRyZW4gZnJvbSA2IHRvIDE3IiwgIkNoaWxkcmVuICN1bmRlciA2IGFuZCBhYm92ZSA2IiwgIk5vIENoaWxkcmVuIikpDQojDQoNCiMjIyBjaGFuZ2UgY291bnQgaW50byBjb2xvci4uLg0KI2dncGxvdChHcm91cGVkTW90aGVyT2NjdXBhdGlvbixhZXMoeD1DaGlsZHJlbikpK2dlb21fcG9pbnQoYWVzKHk9T2NjdXBhdGlvbixzaXplPUF2Z0luY29tZSxjb2xvdXIjPWNvdW50KSkrc2NhbGVfY29sb3VyX2dyYWRpZW50KGxvdz0id2hpdGUiLGhpZ2g9InJlZCIpK3NjYWxlX3hfY29udGludW91cyhicmVha3M9MTo0LCAjbGFiZWxzPWMoIkNoaWxkcmVuIHVuZGVyIDYiLCAiQ2hpbGRyZW4gZnJvbSA2IHRvIDE3IiwgIkNoaWxkcmVuIHVuZGVyIDYgYW5kIGFib3ZlIDYiLCAiTm8gI0NoaWxkcmVuIikpDQoNCg0KI3NjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3VycyA9IHRlcnJhaW4uY29sb3JzKDEwKSkNCmBgYA0KDQpPYnNlcnZhdGlvbnM6DQoxLiBGZW1hbGVzIHdpdGggQ2hpbGRyZW4gZnJvbSA2IHRvIDE3IHVzdWFsbHkgdGVuZCB0byBoYXZlIGhpZ2hlciBhdmVyYWdlIGluY29tZSBhcyB0aGUgZG90IGhhcyBkYXJrZXIgY29sb3IgZm9yIHNldmVyYWwgb2NjdXBhdGlvbnMuIEhvd2V2ZXIsIGZlbWFsZXMgd2l0aCBubyBjaGlsZHJlbiBhbmQgZmVtYWxlcyB3aXRoIGNoaWxkcmVuIG9mIGJvdGggYWdlIGdyb3VwIGhhdmUgbG93ZXIgaW5jb21lLg0KMi4gT2NjdXBhdGlvbiBvZiBFTkcsIE1HUiBhbmQgQ01NIHVzdWFsbHkgdGVuZCB0byBoYXZlIGhpZ2hlciBzYWxhcnkuIE9uIHRoZSBvdGhlciBoYW5kLCBmZW1hbGUgaW4gTEdMIGZpZWxkIGFsd2F5cyBoYXZlIGxvd2VyIHNhbGFyeSwgZXNwZWNpYWxseSBmb3IgZmVtYWxlcyB3aXRoIENoaWxkcmVuIHVuZGVyIDYgd29ya2luZyBpbiBMR0wuDQozLiBJdCBjb25maXJtcyBhZ2FpbiB0aGF0IHRoZXJlIGFyZSBtb3JlIGZlbWFsZXMgd2l0aCBubyBDaGlsZHJlbi4NCg0KDQpDb25jbHVzaW9uOg0KQWZ0ZXIgY29uZHVjdGluZyBhbmFseXNpcyBvbiB0aGUgaW5jb21lIG9mIGZlbWFsZXMgb2YgZGlmZmVyZW50IGdyb3VwcyByZWdhcmRpbmcgdGhlIGNoaWxkcmVuIHByZXNlbmNlIGFuZCBhZ2UgYXMgd2VsbCBhcyBpbnRlcmFjdGluZyB3aXRoIHNvbWUgb3RoZXIgdmFyaWFibGVzLCB3ZSBmaW5kIG91dCB0aGF0IGZlbWFsZXMgd2l0aCBubyBjaGlsZHJlbiBhbmQgZmVtYWxlcyB3aXRoIENoaWxkcmVuIHVuZGVyIDYgYW5kIGFib3ZlIDYgbWF5IGhhdmUgbG93ZXIgaW5jb21lIGNvbXBhcmVkIHRvIHRoZSBvdGhlciB0d28gZ3JvdXBzLg0KDQojI01hcml0YWwgc3RhdHVzZXMgb2YgbW90aGVycw0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KTW90aGVyTWFyaXRhbE9jY3VwYXRpb249c2VsZWN0KERhdGFfd29tZW4sIEluY29tZSxDaGlsZHJlbixPY2N1cGF0aW9uLCBNYXJyaWFnZSwgQWdlKQ0KTW90aGVyTWFyaXRhbE9jY3VwYXRpb24gPC0gbmEub21pdChNb3RoZXJNYXJpdGFsT2NjdXBhdGlvbikNCk1vdGhlck1hcml0YWxPY2N1cGF0aW9uJENoaWxkcmVuIDwtIGlmZWxzZShNb3RoZXJNYXJpdGFsT2NjdXBhdGlvbiRDaGlsZHJlbiA9PSA0LCAwLCAxKQ0KI2RldGFjaChwYWNrYWdlOnBseXIpDQpHcm91cGVkTW90aGVyTWFyaXRhbE9jY3VwYXRpb24gPC0NCiAgTW90aGVyTWFyaXRhbE9jY3VwYXRpb24gJT4lDQogIG5hLm9taXQoKSAlPiUNCiAgZ3JvdXBfYnkoQ2hpbGRyZW4sT2NjdXBhdGlvbiwgTWFycmlhZ2UsIEFnZSkgJT4lIA0KICBzdW1tYXJpemUoDQogICAgQXZnSW5jb21lID0gbWVhbihJbmNvbWUpLA0KICAgIGNvdW50PW4oKQ0KICApIA0KDQpHcm91cGVkTW90aGVyTWFyaXRhbCA8LQ0KICBNb3RoZXJNYXJpdGFsT2NjdXBhdGlvbiAlPiUNCiAgbmEub21pdCgpICU+JQ0KICBncm91cF9ieShDaGlsZHJlbiwgTWFycmlhZ2UsIEFnZSkgJT4lIA0KICBzdW1tYXJpemUoDQogICAgQXZnSW5jb21lID0gbWVhbihJbmNvbWUpLA0KICAgIGNvdW50PW4oKQ0KICApIA0KDQoNCmdncGxvdChHcm91cGVkTW90aGVyTWFyaXRhbCxhZXMoeSA9IEF2Z0luY29tZSwgeCA9QWdlLGNvbG91cj1hcy5mYWN0b3IoQ2hpbGRyZW4pKSkgKw0KZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIGZpbGw9TkEpICsgZmFjZXRfd3JhcCh+TWFycmlhZ2UsIHNjYWxlcz0gImZyZWUiKQ0Kc3VtbWFyeShsbShBdmdJbmNvbWUgfiBBZ2UgKyBJKEFnZV4yKSArIENoaWxkcmVuKk1hcnJpYWdlLCBkYXRhID0gR3JvdXBlZE1vdGhlck1hcml0YWxPY2N1cGF0aW9uKSkNCmBgYA0KDQpPYnNlcnZhdGlvbnM6IFdlIGNhbiBzZWUgaW4gdGhlIHN1bW1hcnkgcmVzdWx0cyBvZiB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiBtYXJpdGFsIHN0YXR1cyBhbmQgbW90aGVyaG9vZCwgc2luZ2xlIG1vdGhlcnMgZWFybiBzaWduaWZpY2FudGx5IGxlc3Mgd2hlbiBvY2N1cGF0aW9ucyBhcmUgcG9vbGVkIGFuZCBhZ2UgaXMgY29udHJvbGxlZC4NCg0KI0VkdWNhdGlvbg0KDQpXZSBleHBlY3QgdGhhdCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdvdWxkIGFmZmVjdCB0aGUgd29tZW4ncyBpbmNvbWUuIFdlIG1heSB3YW50IHRvIGZpZ3VyZSBvdXQgd2hpY2ggZGVncmVlIGlzIHRoZSBtb3N0IGltcG9ydGFudCBmYWN0b3IgdG8gZWFybiBtb3JlIHRoYW4gdGhlIG1lZGlhbiBpbmNvbWUuIEZ1cnRoZXJtb3JlLCB3ZSB3aWxsIHNlZSB3aGljaCBvY2N1cGF0aW9uIGhhcyB0aGUgbGFyZ2VzdC9zbWFsbGVzdCAiYmVsb3cgbWVkaWFuIGdyb3VwIiB3aXRoaW4gZWFjaCBlZHVjYXRpb25hbCBhdHRhaW5tZW50Lg0KDQpXZSBkaXZpZGVkIGZlbWFsZSBpbnRvIDIgZ3JvdXBzICg+PSQ2MCwwMDAgdnMgPDYwLDAwMCkgdXNpbmcgd2VpZ2h0ZWQgbWVkaWFuIGluY29tZSBmb3Igd29ya2luZyBjbGFzcy4gKCQ2MCwwMDApDQpXZSB3aWxsIHNlZSB0aGUgcHJvcG9ydGlvbiBvZiB0aGVzZSAyIGdyb3VwcyBmb3IgZWFjaCBlZHVjYXRpb25hbCBhdHRhaW5tZW50Lg0KDQpgYGB7cn0NCnJlcXVpcmUocGx5cikNCiNDYWxjdWxhdGUgd2VpZ2h0ZWQgbWVkaWFuIHRvIHNwbGl0IGluY29tZSBiZWxvdy9hYm92ZQ0KRGF0YV93PC1zdnlkZXNpZ24oaWQgPSB+MSwgd2VpZ2h0cyA9IH5EYXRhJFdlaWdodCwgZGF0YSA9IERhdGEpDQpzdnlxdWFudGlsZSh+RGF0YSRJbmNvbWUsIERhdGFfdywgYyguMjUsLjUsLjc1KSkNCiMjTWVkaWFuIGluY29tZT0kNjAwMDANCg0KI3NwbGl0IGluY29tZSBiZWxvdy9hYm92ZQ0KVGVtcCRJbmNvbWVfbTwtaWZlbHNlKFRlbXAkSW5jb21lPj02MDAwMCwiPj0kNjAsMDAwIiwiPCQ2MCwwMDAiKQ0KDQpEYXRhX3dvbWVuMjwtc3Vic2V0KFRlbXAsR2VuZGVyPT0nMicpDQphdHRhY2goRGF0YV93b21lbjIpDQpEYXRhX3dvbWVuMjwtZGF0YS5mcmFtZShFZHVjYXRpb24sT2NjdXBhdGlvbixJbmNvbWVfbSxXZWlnaHQpDQpkZXRhY2goRGF0YV93b21lbjIpDQoNCiNnZXQgdGhlIHN1bW1hcnkgdGFibGUtZWR1Y2F0aW9uDQpEYXRhX3dvbWVuX3c8LXN2eWRlc2lnbihpZCA9IH4xLCB3ZWlnaHRzID0gfkRhdGFfd29tZW4yJFdlaWdodCwgZGF0YSA9IERhdGFfd29tZW4yKQ0KdDE8LXByb3AudGFibGUoc3Z5dGFibGUofkluY29tZV9tK0VkdWNhdGlvbiwgRGF0YV93b21lbl93KSwyKQ0KDQpiYXJwbG90KHQxLCBtYWluID0gIkJlbG93L0Fib3ZlIG1lZGlhbiBpbmNvbWUgd29tZW4gYnkgRWR1Y2F0aW9uYWwgYXR0YWlubWVudCIsY29sID0gYygibWlzdHlyb3NlIiwgImxhdmVuZGVyIiksDQp4bGFiID0gIkVkdWNhdGlvbmFsIGF0dGFpbm1lbnQiLCBuYW1lcyA9IGMoIn5nOCIsICJnOX5ub2RlZ3JlZSIsImFzcy9iYWNoIiwicHJvZi9tYXMiLCJkb2MiKSwgDQp5bGFiID0gInByb3BvcnRpb24iLCBsZWdlbmQgPSBjKCI8JDYwLDAwMCIsICI+PSQ2MCwwMDAiKSwgDQphcmdzLmxlZ2VuZCA9IGxpc3QodGl0bGUgPSAiaW5jb21lIiwgeCA9ICJ0b3ByaWdodCIsIGNleCA9IDEpLCB5bGltID0gYygwLCAxLjUpKQ0KYGBgDQoNCk9ic2VydmF0aW9uczoNCg0KMS4gV2l0aG91dCBjb2xsZWdlIGRlZ3JlZSwgYWJvdXQgODAlIG9mIHRoZW0gZWFybiBsZXNzIHRoYW4gbWVkaWFuIGluY29tZS4NCg0KMi4gV2l0aCBtYXN0ZXIncyBvciBkb2N0b3IncyBkZWdyZWUsIGFib3V0IDQwJSBvZiB0aGVtIGVhcm4gbGVzcyB0aGFuIG1lZGlhbiBpbmNvbWUuDQoNCg0KTmV4dCwgd2UgdXNlIGEgbGluZWFyIHJlZ3Jlc3Npb24uDQpgYGB7cn0NCmZpdF9lZHU8LXN2eWdsbShmYWN0b3IoSW5jb21lX20pIH4gZmFjdG9yKEVkdWNhdGlvbiksIGRlc2lnbiA9IERhdGFfd29tZW5fdyxmYW1pbHk9Ymlub21pYWwpDQpzdW1tYXJ5KGZpdF9lZHUpDQoNCmBgYA0KT2JzZXJ2YXRpb25zOg0KDQoxLiBmYWN0b3IyIChncmFkZTl+Y29sbGVnZV9ub19kZWdyZWUpIGlzIG5vdCBzaWduaWZpY2FudC4NCg0KMi4gSW50ZXJwcmV0YXRpb24gZm9yIGZhY3RvcjM6ICJhc3NvY2lhdGUvYmFjaGVsb3IncyBkZWdyZWUiLCB2ZXJzdXMgIn5ncmFkZTgiKGJhc2VsaW5lKSwgbXVsdGlwbGllcyB0aGUgb2RkcyBvZiBiZWluZyAiPj0kNjAwMDAiIGdyb3VwIGJ5IGV4cCgwLjk0MzcyKQ0KDQozLiBXZSBjYW4gYXBwbHkgdGhlIHNhbWUgaW50ZXJwcmV0YXRpb24gZm9yIGZhY3RvciA0LDUsNi4NCg0KNC4gV2l0aGluIGNvbGxlZ2UsIG1hc3RlciwgZG9jdG9yJ3MgZGVncmVlLCB0aGUgY2hhbmNlIG9mIGJlaW5nIGluICI+PSQ2MDAwMCIgZ3JvdXAgaW5jcmVhc2VzIGF0IGhpZ2hlciBlZHVjYXRpb25hbCBhdHRhaW5tZW50Lg0KDQo1LiBIb3dldmVyLCB0aGUgZ2FwIGJldHdlZW4gbWFzdGVyJ3MgYW5kIGRvY3RvcidzIGRlZ3JlZSBpcyByZWxhdGl2ZWx5IHNtYWxsLg0KDQoNClRvIGZ1dGhlciB1bmRlcnN0YW5kIHRoZSBlZmZlY3QsIHdlIGFyZSBnb2luZyB0byBicmVhayBkb3duIGVhY2ggZWR1Y2F0aW9uIGJ5IG9jY3VwYXRpb24uDQpgYGB7cn0NCnQyPC1wcm9wLnRhYmxlKHN2eXRhYmxlKH5JbmNvbWVfbStPY2N1cGF0aW9uK0VkdWNhdGlvbiwgRGF0YV93b21lbl93KSxjKDIsMykpDQojYnJlYWsgZG93biBpbnRvIG9jY3VwYXRpb24NCiMjI35ncmFkZTgNCmJhcnBsb3QodDJbLCwxXSxtYWluID0gIn5ncmFkZTgsIGJ5IG9jY3VwYXRpb24iLGNvbCA9IGMoIm1pc3R5cm9zZSIsICJ3aGl0ZSIpLA0KeGxhYiA9ICJvY2N1cGF0aW9uIiwgbmFtZXMgPSBjKCdNR1InLCAnQ01NJywgJ0ZJTicsICdMR0wnLCAnTUVEJyAsICdCVVMnLCAnRU5HJywgJ1NDSScpLCANCnlsYWIgPSAicHJvcG9ydGlvbiIsIGxlZ2VuZCA9IGMoIjwkNjAsMDAwIiwgIj49JDYwLDAwMCIpLCANCmFyZ3MubGVnZW5kID0gbGlzdCh0aXRsZSA9ICJJbmNvbWUiLCB4ID0gInRvcHJpZ2h0IiwgY2V4ID0gMSksIHlsaW0gPSBjKDAsIDEuNSkpDQoNCmBgYA0KT2JzZXJ2YXRpb25zOg0KDQoxLiBXaXRoaW4gIn5ncmFkZTgiLCAiRklOOmZpbmFuY2UiIGhhcyB0aGUgbGFyZ2VzdCA8JDYwLDAwMCBncm91cC4NCg0KMi4gIkNNTTpjb21wdXRlciBvY2NzIiBoYXMgdGhlIHNtYWxsZXN0IDwkNjAsMDAwIGdyb3VwLg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRX0NCiMjI2dyYWRlOX5jb2xsZWdlX25vX2RlZ3JlZQ0KYmFycGxvdCh0MlssLDJdLG1haW4gPSAiZ3JhZGU5fmNvbGxlZ2Vfbm9fZGVncmVlLCBieSBvY2N1cGF0aW9uIixjb2wgPSBjKCJtaXN0eXJvc2UiLCAid2hpdGUiKSwNCnhsYWIgPSAib2NjdXBhdGlvbiIsIG5hbWVzID0gYygnTUdSJywgJ0NNTScsICdGSU4nLCAnTEdMJywgJ01FRCcgLCAnQlVTJywgJ0VORycsICdTQ0knKSwgDQp5bGFiID0gInByb3BvcnRpb24iLCBsZWdlbmQgPSBjKCI8JDYwLDAwMCIsICI+PSQ2MCwwMDAiKSwgDQphcmdzLmxlZ2VuZCA9IGxpc3QodGl0bGUgPSAiSW5jb21lIiwgeCA9ICJ0b3ByaWdodCIsIGNleCA9IDEpLCB5bGltID0gYygwLCAxLjUpKQ0KDQpgYGANCk9ic2VydmF0aW9uczoNCg0KMS4gV2l0aGluICJncmFkZTl+Y29sbGVnZV9ub19kZWdyZWUiLCAiU0NJOnNjaWVuY2UiIGhhcyB0aGUgbGFyZ2VzdCA8JDYwLDAwMCBncm91cC4NCg0KMi4gIkNNTTpjb21wdXRlciBvY2NzIiBoYXMgdGhlIHNtYWxsZXN0IDwkNjAsMDAwIGdyb3VwLg0KDQpgYGB7ciBlY2hvID0gRkFMU0V9DQojIyNhc3NvY2lhdGUvYmFjaGVsb3INCmJhcnBsb3QodDJbLCwzXSxtYWluID0gImFzc29jaWF0ZS9iYWNoZWxvciwgYnkgb2NjdXBhdGlvbiIsY29sID0gYygibWlzdHlyb3NlIiwgIndoaXRlIiksDQp4bGFiID0gIm9jY3VwYXRpb24iLCBuYW1lcyA9IGMoJ01HUicsICdDTU0nLCAnRklOJywgJ0xHTCcsICdNRUQnICwgJ0JVUycsICdFTkcnLCAnU0NJJyksIA0KeWxhYiA9ICJwcm9wb3J0aW9uIiwgbGVnZW5kID0gYygiPCQ2MCwwMDAiLCAiPj0kNjAsMDAwIiksIA0KYXJncy5sZWdlbmQgPSBsaXN0KHRpdGxlID0gIkluY29tZSIsIHggPSAidG9wcmlnaHQiLCBjZXggPSAxKSwgeWxpbSA9IGMoMCwgMS41KSkNCg0KYGBgDQpPYnNlcnZhdGlvbnM6DQoNCjEuIFdpdGhpbiAiYXNzb2NpYXRlL2JhY2hlbG9yIiwgIkxHTDpsZWdhbCIgaGFzIHRoZSBsYXJnZXN0IDwkNjAsMDAwIGdyb3VwLg0KDQoyLiAiQ01NOiBjb21wdXRlciBvY2NzIiBoYXMgdGhlIHNtYWxsZXN0IDwkNjAsMDAwIGdyb3VwLg0KDQpgYGB7ciBlY2hvID0gRkFMU0V9DQojIyNtYXN0ZXIvcHJvZmVzc2lvbmFsDQpiYXJwbG90KHQyWywsNF0sbWFpbiA9ICJtYXN0ZXIsIGJ5IG9jY3VwYXRpb24iLGNvbCA9IGMoIm1pc3R5cm9zZSIsICJ3aGl0ZSIpLA0KeGxhYiA9ICJvY2N1cGF0aW9uIiwgbmFtZXMgPSBjKCdNR1InLCAnQ01NJywgJ0ZJTicsICdMR0wnLCAnTUVEJyAsICdCVVMnLCAnRU5HJywgJ1NDSScpLCANCnlsYWIgPSAicHJvcG9ydGlvbiIsIGxlZ2VuZCA9IGMoIjwkNjAsMDAwIiwgIj49JDYwLDAwMCIpLCANCmFyZ3MubGVnZW5kID0gbGlzdCh0aXRsZSA9ICJJbmNvbWUiLCB4ID0gInRvcHJpZ2h0IiwgY2V4ID0gMSksIHlsaW0gPSBjKDAsIDEuNSkpDQoNCmBgYA0KT2JzZXJ2YXRpb25zOg0KDQoxLiBXaXRoaW4gIk1hc3RlciIsICJMR0w6bGVnYWwiIGhhcyB0aGUgbGFyZ2VzdCA8JDYwLDAwMCBncm91cC4NCg0KMi4gIkNNTTpjb21wdXRlciBvY2NzIiBoYXMgdGhlIHNtYWxsZXN0IDwkNjAsMDAwIGdyb3VwLg0KDQpgYGB7ciBlY2hvID0gRkFMU0V9DQojZG9jdG9yDQpiYXJwbG90KHQyWywsNV0sbWFpbiA9ICJkb2N0b3IsIGJ5IG9jY3VwYXRpb24iLGNvbCA9IGMoIm1pc3R5cm9zZSIsICJ3aGl0ZSIpLA0KeGxhYiA9ICJvY2N1cGF0aW9uIiwgbmFtZXMgPSBjKCdNR1InLCAnQ01NJywgJ0ZJTicsICdMR0wnLCAnTUVEJyAsICdCVVMnLCAnRU5HJywgJ1NDSScpLCANCnlsYWIgPSAicHJvcG9ydGlvbiIsIGxlZ2VuZCA9IGMoIjwkNjAsMDAwIiwgIj49JDYwLDAwMCIpLCANCmFyZ3MubGVnZW5kID0gbGlzdCh0aXRsZSA9ICJJbmNvbWUiLCB4ID0gInRvcHJpZ2h0IiwgY2V4ID0gMSksIHlsaW0gPSBjKDAsIDEuNSkpDQojI01HUiBpcyB0aGUgYmVzdCwgTEdMIGlzIHRoZSB3b3JzdA0KYGBgDQpPYnNlcnZhdGlvbnM6DQoNCjEuIFdpdGhpbiAiRG9jdG9yIiwgIkxHTDpsZWdhbCIgaGFzIHRoZSBsYXJnZXN0IDwkNjAsMDAwIGdyb3VwLg0KDQoyLiAiQ01NOmNvbXB1dGVyIG9jY3MiIGhhcyB0aGUgc21hbGxlc3QgPCQ2MCwwMDAgZ3JvdXAuDQoNCkNvbmNsdXNpb25zOg0KDQoxLiBXb21lbiB3aXRob3V0IGNvbGxlZ2UgZGVncmVlIGlzIG1vcmUgbGlrZWx5IHRvIGVhcm4gbGVzcyB0aGFuIG1lZGlhbiBpbmNvbWUuDQoNCjIuICgtKSBBdCBhbnkgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCxDTU06Y29tcHV0ZXIgb2NjcyBoYXMgdGhlIHNtYWxsZXN0IDwkNjAsMDAwIGdyb3VwLg0KDQozLiAoKykgV2l0aCB0aGUgYmFjaGVsb3IvbWFzdGVyL2RvY3RvcidzIGRlZ3JlZSBMR0w6bGVnYWwgaGFzIHRoZSBsYXJnZXN0ID49JDYwLDAwMCBncm91cC4NCiAgDQogDQogIA0KDQpgYGB7ciBlY2hvID0gRkFMU0V9DQpEYXRhIDwtIFRlbXANCmBgYA0KDQojIFJlZ2lvbmFsDQoNCllvdSBjYW5ub3QgY2hvb3NlIHdoZXJlIHlvdSB3ZXJlIGJvcm4sIGJ1dCB5b3UgY2FuIGNob29zZSB3aGVyZSB5b3UgbGl2ZS4gRGlmZmVyZW50IHBsYWNlcyBzZW5kcyBkaWZmZXJlbnQgbWVzc2FnZXMgYW5kIGF0dHJhY3RzIGRpZmZlcmVudCBwZW9wbGUuIEluIHRoaXMgc2VjdGlvbiB3ZSBhcmUgaW50ZXJlc3RlZCB0byBzZWUgcmVnaW9uYWwgZWZmZWN0IG9uIHdvbWVuJ3MgaW5jb21lIGluIHRoZSBVUy4gVGhlIG1haW4gcXVlc3Rpb24gaGVyZSBpczogaW4gd2hpY2ggbG9jYXRpb25zIGFyZSB3b21lbiBiZXR0ZXIgb3Igd29yc2Ugb2ZmPw0KDQpGaXJzdCwgd2Ugd2FudCB0byBsb29rIGF0IHdvbWVuJ3MgaW5jb21lIGJveHBsb3RzIGluIGFsbCA0IHJlZ2lvbnMgdG8gYmV0dGVyIHVuZGVyc3RhbmQgd29tZW4ncyBpbmNvbWUgZGlzdHJpYnV0aW9uLiANCg0KYGBge3IsZWNobyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpEVz1EYXRhW0RhdGEkR2VuZGVyPT0yLCBdDQoNCiMgUmVjb2RlIFN0YXRlIE5hbWVzIGJlZm9yZSBib3hwbG90DQpyZXF1aXJlKHJlYWRyKQ0Kc3RhdGVuYW1lcyA8LSByZWFkX2NzdihmaWxlLmNob29zZSgpKQ0KI3N0YXRlbmFtZXMuY3N2IGZpbGUgY29tZXMgZnJvbSBkcm9wYm94IGRhdGEgZm9sZGVyIFByb2YgZ2F2ZSB1cw0KDQpuYW1lcyhEVylbOV08LSJjb2RlIg0KRFcubiA8LSBtZXJnZShEVywgc3RhdGVuYW1lcywgYnk9ImNvZGUiKQ0KDQoNCiMgYm94cGxvdCBvZiBlYWNoIHJlZ2lvbiB0byBzZWUgZGlzdHJpYnV0aW9uDQpyZXF1aXJlKHBsb3RseSkNCiBtID0gbGlzdCgNCiAgbCA9MTUwLA0KICByID0gNTAsDQogIGIgPSAxMDAsDQogIHQgPSAxMDAsDQogIHBhZCA9IDQNCikNCmBgYA0KVGhlIGJveHBsb3RzIG9mIHdvbWVuJ3MgaW5jb21lIHNob3cgdGhhdCBkZXNwaXRlIHRoYXQgYWxsIGRpc3RyaWJ1dGlvbnMgYXJlIGhpZ2hseSBza2V3ZWQgdG8gdGhlIHJpZ2h0LCB0aGUgTm9ydGhlYXN0IFJlZ2lvbiBoYXMgdGhlIGhpZ2hlc3Qgd29tZW4ncyBpbmNvbWUgbGV2ZWwgb2YgYWxsIDQgcmVnaW9ucywgZm9sbG93ZWQgYnkgdGhlIFdlc3Q7IE1pZHdlc3QgaGFzIHRoZSBsb3dlc3Qgd29tZW4ncyBpbmNvbWUgbGV2ZWwsIHdoZXJlYXMgU291dGggaXMgb25seSBzbGlnaHRseSBiZXR0ZXIgb2ZmIHRoYW4gdGhhdC4gVGhlbiB3ZSB3aWxsIGJyZWFrIGRvd24gdG8gc3RhdGUgbGV2ZWwgdG8gaW52ZXN0aWdhdGUgZnVydGhlciBvbiB3b21lbidzIGluY29tZSBsZXZlbC4NCg0KSW5jb21lIGxldmVscyBjYW4gYmUgYWZmZWN0ZWQgYnkgbWFueSB0aGluZ3MuIENvc3Qgb2YgbGl2aW5nIGlzIG9uZSBvZiB0aGVtLiBGb3IgZXhhbXBsZSwgSW4gTmV3IFlvcmssIGV2ZXJ0aGluZyBjb3N0IGEgbGl0dGxlIG1vcmUgdGhhbiBtYW55IG90aGVyIHBhcnRzIG9mIHRoZSBVUywgc28gcGVvcGxlIHdpbGwgb25seSB0aHJpdmUgYnkgZWFybmluZyBtb3JlIG1vbmV5LiBUaGVyZWZvcmUsIGluIG9yZGVyIHRvIHJlbW92ZSB0aGUgZWZmZWN0IG9mIGNvc3Qgb2YgbGl2aW5nIHRoYXQgZGlmZmVycyBpbiBkaWZmZXJlbnQgc3RhdGVzLCB3ZSBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2Ugb2YgbWVkaWFuIG9mIGVhY2ggd29tYW4ncyBpbmNvbWUgYnkgc3RhdGUgYW5kIGRyYXcgYm94cGxvdCBhY2NvcmRpbmcgdG8gdGhhdC4NCg0KYGBge3IsZWNobyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI3BlcmNlbnRhZ2UgbWVkaWFuIG9mIHdvbWVuIGFuZCBtZW4gaW4gZWFjaCBzdGF0ZSB0byByZW1vdmUgY29zdCBvZiBsaXZpbmcNCnJlcXVpcmUoZHBseXIpDQpHZW5NZWRpYW49YWdncmVnYXRlKEluY29tZX5TdGF0ZSxEYXRhLG1lZGlhbikNCm5hbWVzKEdlbk1lZGlhbilbMV08LSJjb2RlIg0KR2VuTWVkaWFuIDwtIG1lcmdlKEdlbk1lZGlhbiwgc3RhdGVuYW1lcywgYnk9ImNvZGUiKQ0KQWxsTWVkaWFuPUdlbk1lZGlhbiRJbmNvbWVbbWF0Y2goRFcubiRuYW1lLEdlbk1lZGlhbiRuYW1lKV0NCkluY29tZVN0YXRlPWNiaW5kKERXLm4kSW5jb21lL0FsbE1lZGlhbixEVy5uJG5hbWUpDQpjb2xuYW1lcyhJbmNvbWVTdGF0ZSk8LWMoIlBlcmNlbnRhZ2Vfb2ZfTWVkaWFuIiwiU3RhdGUiKQ0KUGVyYz1hcy5kYXRhLmZyYW1lKEluY29tZVN0YXRlKQ0KUGVyYyRQZXJjZW50YWdlX29mX01lZGlhbiA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihQZXJjJFBlcmNlbnRhZ2Vfb2ZfTWVkaWFuKSkNCnBsb3RfbHkoUGVyYywgeSA9IFBlcmNlbnRhZ2Vfb2ZfTWVkaWFuLCBjb2xvciA9IFN0YXRlLCB0eXBlID0gImJveCIpJT4lDQogIGxheW91dChhdXRvc2l6ZSA9IEYsIHdpZHRoID0gODAwLCBoZWlnaHQgPSA1MDAsIG1hcmdpbiA9IG0pDQpgYGANCkZyb20gdGhpcyBpcmlzZGVzY2VudCBib3hwbG90IGJ5IHN0YXRlLCB3ZSBjYW4gc2VlIHRoYXQgTmV3IFlvcmsgZGVmaW5pdGVseSBnb2VzIGFoZWFkIChkZXNwaXRlIHRoYXQgaXRzIGNvc3Qgb2YgbGl2aW5nIGlzIGFscmVhZHkgaGlnaCksIHNvIGRvZXMgQ29ubmVjdGljdXQgd2l0aCBtb3JlIGxhcmdlIGV4dHJlbWUgdmFsdWVzOyBob3dldmVyIENhbGlmb3JuaWEgaGFzIHRoZSBoaWdoZXN0IHVwcGVyIHdoaXNrZXIgYW5kIGxhcmdlc3QgcG9ydGlvbiBvZiB1cHBlciBtaWRkbGUgaW5jb21lOyBVdGFoIGFuZCBXeW9taW5nIGFyZSB0aGUgd29yc3Qgb2ZmLg0KICANClRoZW4gd2Ugd2FudCB0byBkZWNpZGUgbG9jYXRpb25zIHdoZXJlIHdvbWVuIHdpbGwgdGhyaXZlIG1vc3QgZmluYW5jaWFsbHkgKHJlbGF0aXZlbHkgdG8gbWVuKSwgc28gd2UgcGxvdCB3b21lbidzIG1lZGlhbiBvZiBwZXJjZW50YWdlIGluY29tZSBieSBzdGF0ZSBpbiBhIFVTIG1hcCwgd2hpY2ggc2hvd3MgdGhlIHBlcmNlbnRhZ2Ugb2Ygc3RhdGV3aXNlIG1lZGlhbiB0aGF0IGhhbGYgb2Ygd29tZW4gaGFzIGluY29tZSBiZWxvdy4gSW4gcGVyZmVjdCBlcXVhbC1nZW5kZXIgc2NlbmFyaW9zLCB0aGUgcGVyY2VudGFnZSBzaG91bGQgYmUgMSwgd2hpY2ggbWVhbnMgaGFsZiBvZiB3b21lbiBoYXZlIGluY29tZSBiZWxvdyB0aGUgZXhhY3Qgc3RhdGV3aXNlIG1lZGlhbi4NCiAgICANCmBgYHtyLGVjaG8gPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgTWFwIHdvbWVuJ3MgbWVkaWFuIG9mIHBlcmNlbnRhZ2Ugb2YgbWVkaWFuIGJ5IHN0YXRlDQpQZXJjTSA8LSBhZ2dyZWdhdGUoUGVyY2VudGFnZV9vZl9NZWRpYW5+U3RhdGUsUGVyYywgbWVkaWFuKQ0KbmFtZXMoUGVyY00pWzFdPC0ibmFtZSINClBNIDwtIG1lcmdlKFBlcmNNLCBzdGF0ZW5hbWVzLCBieT0ibmFtZSIpDQoNCiMgbGlnaHQgZ3JleSBib3VuZGFyaWVzDQpsIDwtIGxpc3QoY29sb3IgPSB0b1JHQigid2hpdGUiKSwgd2lkdGggPSAxKQ0KIyBzcGVjaWZ5IHNvbWUgbWFwIHByb2plY3Rpb24vb3B0aW9ucw0KZyA8LSBsaXN0KA0KICBzY29wZSA9ICd1c2EnLA0KICBwcm9qZWN0aW9uID0gbGlzdCh0eXBlID0gJ2FsYmVycyB1c2EnKSwNCiAgc2hvd2xha2VzID0gVFJVRSwNCiAgbGFrZWNvbG9yID0gdG9SR0IoJ3doaXRlJykNCikNCnBsb3RfbHkoUE0sIHogPSBQZXJjZW50YWdlX29mX01lZGlhbiwgbG9jYXRpb25zID0gYWJiciwgdGV4dD1uYW1lLCB0eXBlID0gJ2Nob3JvcGxldGgnLA0KICAgICAgICBsb2NhdGlvbm1vZGUgPSAnVVNBLXN0YXRlcycsIGNvbG9yID0gUGVyY2VudGFnZV9vZl9NZWRpYW4sIGNvbG9ycyA9ICdCbHVlcycsDQogICAgICAgIG1hcmtlciA9IGxpc3QobGluZSA9IGwpLCBjb2xvcmJhciA9IGxpc3QodGl0bGUgPSAiTWVkaWFuIFBlcmNlbnRhZ2UiKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICcyMDE0IE1lZGlhbiBvZiBXb21hbiBQZXJjZW50YWdlIEluY29tZSBieSBTdGF0ZScsIGdlbyA9IGcsYXV0b3NpemUgPSBGLCB3aWR0aCA9IDgwMCwgaGVpZ2h0ID0gNTAwLCBtYXJnaW4gPSBtKQ0KDQpgYGANClRoaXMgbWFwIGNsZWFybHkgc2hvd3MgdGhhdCBVdGFoIGlzIHdoZXJlIHdvbWVuIHRocml2ZSBtb3N0IGZpbmFuY2lhbGx5IChyZWxhdGl2ZWx5IHRvIG1lbikuIEhhbGYgb2Ygd29tZW4gaW4gVXRhaCBoYXZlIGluY29tZSBiZWxvdyA2OC45NyUgb2Ygc3RhdGUgbWVkaWFuLCBjb21wYXJlZCB0byAxMDAlIGluIHRoZSBwZXJmZWN0IGVxdWFsLWdlbmRlciBzaXR1YXRpb24uIFN1cnByaXNpbmdseSAoYXQgbGVhc3QgdG8gdXMpLCBELkMuIHRvcHMgYW1vbmcgYWxsIHN0YXRlcyB3aXRoIGEgOTMlLCBmb2xsb3dlZCBieSBOZXZhZGEgOTIlIGFuZCBBcml6b25hIDkwJS4NCiAgDQogIA0KQ29uY2x1c2lvbjogV29tZW4ncyBpbmNvbWUgZGlzdHJpYnV0aW9ucyBpbiBlYWNoIHN0YXRlIGFyZSBhbGwgaGlnaGx5IHNrZXdlZCB0byB0aGUgcmlnaHQgd2l0aCBsb3RzIG9mIGxhcmdlIGV4dHJlbWUgdmFsdWVzLiANCjEuIFRoZSBOb3J0aGVhc3QgUmVnaW9uIGhhcyB0aGUgaGlnaGVzdCB3b21lbidzIGluY29tZSBsZXZlbCBvZiBhbGwgNCByZWdpb25zIGluIHRoZSBVUy4gMi4gQWZ0ZXIgZXhjbHVkaW5nIHN0YXRld2lzZSBkaWZmZXJlbmNlcyBlLmcuIGNvc3Qgb2YgbGl2aW5nLCB3b21lbiBpbiBOZXcgWW9yayBhbmQgQ29ubmVjdGljdXQgdGVuZCB0byBoYXZlIGhpZ2hlciBpbmNvbWVzLCBDYWxpZm9ybmlhIGhhcyB0aGUgaGlnaGVzdCB1cHBlciB3aGlza2VyIGFuZCBsYXJnZXN0IHBvcnRpb24gb2YgdXBwZXIgbWlkZGxlIGluY29tZSwgYW5kIFV0YWggYW5kIFd5b21pbmcgYXJlIHRoZSB3b3JzdCBvZmYuIA0KMy4gQnkgY29tcGFyaW5nIHdvbWVuJ3MgaW5jb21lIG1lZGlhbnMgd2l0aCBzdGF0ZSBtZWRpYW5zLCB3ZSBzZWUgdGhhdCBoYWxmIG9mIFV0YWgncyB3b21lbiBoYXZlIGluY29tZSBiZWxvdyA2OSUgb2Ygc3RhdGUgbWVkaWFuLCB3aGljaCBpcyB0aGUgbG93ZXN0IHBlcmNlbnRhZ2UgYW1vbmcgYWxsIHN0YXRlcy4gV29tYW4gaW4gRC5DLiwgTmV2YWRhLCBhbmQgQXJpem9uYSBoYXZlIGluY29tZSBtZWRpYW5zIGNsb3Nlc3QgdG8gc3RhdGUgbWVkaWFuLCB3aXRoIHBlcmNlbnRhZ2UgYWJvdmUgOTAlLCB3aGVyZWFzIG90aGVyIHN0YXRlcycgYXJlIG11Y2ggbG93ZXIuDQoNCiNSYWNlDQoNCk92ZXIgdGhlIHllYXJzLCB0aGVyZSBoYXMgYmVlbiBhbiBpbmNyZWFzZSBhd2FyZW5lc3Mgb24gdGhlIHdvbWVuIHdhZ2UgZ2FwIGFuZCByYWNpYWwgc29jaWFsIGlzc3Vlcy4gV2Ugd2FudGVkIHRvIHVuZGVyc3RhbmQgdGhlIGVmZmVjdHMgb2YgYSB3b21lbidzIHJhY2UgY291bGQgcG90ZW50aWFsbHkgaGF2ZSBvbiBhIHdvbWVuJ3MgY2FyZWVyLiANCg0KRmlyc3QsIHdlIGJyb2tlIGRvd24gdGhlIGRhdGEgb2Ygd29tZW4gYnkgcmFjZS4NCmBgYHtyIGVjaG8gPSBGQUxTRX0NClJhY2VfZnJlcSA8LSBmdGFibGUoRGF0YV93b21lbiRSYWNlKQ0KUmFjZV9mcmVxIDwtIGFzLmRhdGEuZnJhbWUoUmFjZV9mcmVxKQ0KDQpwbG90X2x5KFJhY2VfZnJlcSwgbGFiZWxzID0gVmFyMSwgdmFsdWVzID0gRnJlcSwgdHlwZSA9ICJwaWUiLGhvbGUgPSAwLjAsbmFtZSA9ICJSYWNlIikgJT4lDQogIGxheW91dCh0aXRsZSA9ICJQZXJjZW50YWdlIG9mIFdvbWVuIGJ5IFJhY2UiKQ0KYGBgDQpGcm9tIHRoZSBwaWUgY2hhcnQsIHdlIGRldGVybWluZWQgdGhhdCBtYWpvcml0eSBvZiB3b21lbiBpbiB0aGUgd29yayBmb3JjZSBhcmUgd2hpdGUuIFRvIHNlZSBob3cgdGhpcyBjb21wYXJlcyB0byB0aGUgbmF0aW9uYWwgYXZlcmFnZSwgd2UgY29tcGFyZWQgdGhpcyBjaGFydCB0byB0aGUgb3ZlcmFsbCByYWNlIGJyZWFrZG93biBvZiB0aGUgY291bnRyeS4gT3VyIGFzc3VtcHRpb24gaXMgdGhhdCB3b21lbiBzaG91bGQgbWFrZSB1cCBoYWxmIG9mIHRoZSB3b3JraW5nIGZvcmNlIGZvciBhbGwgcmFjZXMuIA0KDQpgYGB7ciBlY2hvID0gRkFMU0V9DQpSYWNlX2ZyZXFfQWxsIDwtIGZ0YWJsZShEYXRhJFJhY2UpDQpSYWNlX2ZyZXFfQWxsIDwtIGFzLmRhdGEuZnJhbWUoUmFjZV9mcmVxX0FsbCkNCg0KUmFjZV9Db21wYXJlIDwtIGRhdGEuZnJhbWUoUmFjZV9mcmVxJFZhcjEsUmFjZV9mcmVxJEZyZXEsMC41ICpSYWNlX2ZyZXFfQWxsJEZyZXEsMTAwKihSYWNlX2ZyZXEkRnJlcS0wLjUgKlJhY2VfZnJlcV9BbGwkRnJlcSkvUmFjZV9mcmVxX0FsbCRGcmVxKQ0KY29sbmFtZXMoUmFjZV9Db21wYXJlKSA8LSBjKCdSYWNlJywnV29tZW4nLCc1MCUgb2YgR2VuZXJhbCBwb3B1bGF0aW9uJywnUGVyY2VudGFnZSBEaWZmZXJlbmNlICglKScpDQpSYWNlX0NvbXBhcmUNCmBgYA0KT2JzZXJ2YXRpb246DQoNCjEuIEZyb20gdGhlIHRhYmxlLCB3ZSBjYW4gZ2F0aGVyIHRoYXQgQmxhY2sgd29tZW4gYXJlIDExJSBoaWdoZXIgdGhhbiB0aGUgaGFsZiBvZiB0aGUgQmxhY2sgd29ya2ZvcmNlLiBUaGlzIG1lYW5zIG1vcmUgYmxhY2sgd29tZW4gYXJlIHdvcmtpbmcgdGhhbiBtYW4uIA0KDQoyLiBBbGwgb3RoZXIgcmFjZXMgaGF2ZSBhIHJlbGF0aXZlbHkgc21hbGwgZGlmZmVyZW5jZS4gDQoNCjMuIFdvcmtmb3JjZSBncm91cHMgd2l0aCBtb3JlIG1lbiB0aGFuIHdvbWVuIGFyZSBXaGl0ZSwgQXNpYW4sIGFuZCBPdGhlcnMuDQoNCg0KV2UgYWxzbyB3YW50IHRvIGxvb2sgaW50byBob3cgd29tZW4gcGVyZm9ybSBpbiB0aGUgb2NjdXBhdGlvbi4gV2UgYnJva2UgdXAgdGhpcyBpbnRvIHRocmVlIGNhdGVnb3JpZXM6IA0KDQoxLiBXb21lbiB3aG8gcGVyZm9ybSB1bmRlciB0aGUgd2VpZ2h0ZWQgbWVhbiBvZiB3b21lbg0KDQoyLiBXb21lbiB3aG8gcGVyZm9ybSBhYm92ZSB0aGUgd2VpZ2h0ZWQgbWVhbiBvZiBib3RoIGdlbmRlcnMNCg0KMy4gV29tZW4gd2hvIHBlcmZvcm0gYWJvdmUgdGhlIHdlaWdodGVkIG1lYW4gb2YgbWVuIA0KDQpUaGVzZSBjYXRlZ29yaWVzIHdpbGwgYmUgY2xhc3NpZmllZCBhcyBiZWxvdywgbWVldCwgYW5kIGV4Y2VlZCByZXNwZWN0aXZlbHkuIA0KYGBge3IgZWNobyA9IEZBTFNFfQ0KI0NvbXBhcmluZyB3aXRoIEhpc3RvZ3JhbXMNCkRTT1JfVyA8LSBkYXRhLmZyYW1lKERhdGFfc2V4X29jY3BfcmFjZVt3aGljaChEYXRhX3NleF9vY2NwX3JhY2UkR2VuZGVyPT0yKSxdKQ0KDQpwIDwtIGdncGxvdChEU09SX1csIGFlcyh4PVJhY2UseT1NRUFOLCBmaWxsPWZhY3RvcihSYWNlKSkpICsNCiAgICAgICAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIixzdGF0PSJpZGVudGl0eSIpKw0KICAgICAgICAgICAgZmFjZXRfZ3JpZCguIH4gT2NjdXBhdGlvbikrDQogICAgICAgICAgICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gTUVBTiksZGF0YT1EYXRhX3NleF9vY2NwX3dvbWVuKSsNCiAgICAgICAgICAgIGdlb21fdGV4dChhZXMoMSwwLjUsbGFiZWwgPSAiV29tZW4ncyBNZWFuIikpKw0KICAgICAgICAgICAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gYnkgUmFjZSBvZiBGZW1hbGVzIGNvbXBhcmVkIHRvIFdvbWVuJ3MgTWVhbiIpKw0KICAgICAgICAgICAgbGF5b3V0KGF1dG9zaXplID0gRiwgd2lkdGggPSAxMDAwLCBoZWlnaHQgPSA4MDAsIG1hcmdpbiA9IG0pDQpnZ3Bsb3RseShwKQ0KYGBgDQpGcm9tIHRoZSBncmFwaCwgd2Ugbm90aWNlcyB0aGF0IG1ham9yaXR5IG9mIG9jY3VwYXRpb24gd2VyZSBub3QgbWVldGluZyB0aGUgY3JpdGVyaWEuIFRvIGdhaW4gYSBiZXR0ZXIgdW5kZXJzdGFuZCwgd2UgdG9vayBpbnRvIGFjY291bnQgaGUgcG9wdWxhdGlvbiBzaXplLiANCmBgYHtyIGVjaG8gPSBGQUxTRX0NCnggPC0gZnRhYmxlKERhdGFfd29tZW4kUmFjZSxEYXRhX3dvbWVuJE9jY3VwYXRpb24pDQp4IDwtIGFzLmRhdGEuZnJhbWUoeCkNCnggPC0geFstMzEsXSAjZnJlcXVlbmN5IG9mIHplcm8NCg0KRFNPUl9XX0ZyZXEgPC0gZGF0YS5mcmFtZShEU09SX1cseCRGcmVxKQ0KDQpCYXNlIDwtIGdncGxvdChEU09SX1dfRnJlcSwgYWVzKHg9UmFjZSx5PU1FQU4pLGNvbG91ciA9IGZhY3RvcihEU09SX1dfRnJlcSRSYWNlKSkgKw0KICAgICAgICAgICAgZmFjZXRfZ3JpZCguIH4gT2NjdXBhdGlvbikrDQogICAgICAgICAgICBnZW9tX3BvaW50KGFlcyhzaXplID0gRFNPUl9XX0ZyZXEkeC5GcmVxLGNvbG9yID0gZmFjdG9yKERTT1JfV19GcmVxJFJhY2UpKSkrDQogICAgICAgICAgICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBieSBSYWNlIG9mIEZlbWFsZXMgdXNpbmcgU2l6ZSIpKw0KICAgICAgICAgICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IE1FQU4pLGNvbG91cj0iZGVlcHBpbmsxIixkYXRhPURhdGFfc2V4X29jY3Bfd29tZW4pKw0KICAgICAgICAgICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IE1FQU4pLGNvbG91cj0iYmx1ZSIsZGF0YT1EYXRhX3NleF9vY2NwX21lbikrDQogICAgICAgICAgICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gTUVBTiksY29sb3VyPSJncmVlbiIsZGF0YT1EYXRhX29jY3UpKw0KICAgICAgICAgICAgbGF5b3V0KGF1dG9zaXplID0gRiwgd2lkdGggPSAxMDAwLCBoZWlnaHQgPSA4MDAsIG1hcmdpbiA9IG0pDQpnZ3Bsb3RseShCYXNlKQ0KDQpgYGANCk9iZXJzZXJ2YXRpb25zOg0KDQoxLiBBc2lhbnMgd29tZW4gZWFybiBzaWduaWZpY2FudGx5IGhpZ2hlciBpbmNvbWUgdGhhbiBvdGhlciByYWNlcy4NCg0KMi4gVGhlIGF2ZXJhZ2UgZm9yIHdvbWVuIGlzIHZlcnkgY2xvc2UgdGhlIFdoaXRlIHdvbWVuIGJlY2F1c2UgdGhleSBhY2NvdW50IGZvciBtb3N0IG9mIHRoZSB3b3JrZm9yY2UuDQoNCjMuIFRoZXJlIGFyZSBubyBncm91cHMgb2Ygd29tZW4gdGhhdCBhcmUgaGlnaGVyIHRoYW4gdGhlIG1lZGlhbiBvZiBtZW4NCg0KRnJvbSB0aGUgcGxvdCwgd2UgYWxzbyBzZWUgYSBsb3Qgb2YgbWlub3JpdHkgZ3JvdXBzIHRvd2FyZCB0aGUgYm90dG9tLiBUaGUgZnJlcXVlbmN5IGZvciB0aGVzZSBmcm91cHMgd2VyZSBvZnRlbiB2ZXJ5IHNtYWxsLiBUbyBoZWxwIGdhaW4gYSBiZXR0ZXIgdW5kZXJzdGFuZGluZywgd2UgdG9vayBvdXQgYWxsIGdyb3VwcyB3aXRoIGxlc3MgdGhhbiA1MCBwZW9wbGUgaW4gdGhlIGNhdGVnb3J5LiANCmBgYHtyIGVjaG8gPSBGQUxTRX0NCkRTT1JfV19GcmVxX2ZpbHRlcmVkIDwtIGZpbHRlcihEU09SX1dfRnJlcSwgeC5GcmVxID4gNTApDQoNCkJhc2VfZmlsbCA8LSBnZ3Bsb3QoRFNPUl9XX0ZyZXFfZmlsdGVyZWQsIGFlcyh4PVJhY2UseT1NRUFOKSxjb2xvdXIgPSBmYWN0b3IoRFNPUl9XX0ZyZXFfZmlsdGVyZWQkUmFjZSkpICsNCiAgICAgICAgICAgIGZhY2V0X2dyaWQoLiB+IE9jY3VwYXRpb24pKw0KICAgICAgICAgICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IERTT1JfV19GcmVxX2ZpbHRlcmVkJHguRnJlcSxjb2xvciA9IGZhY3RvcihEU09SX1dfRnJlcV9maWx0ZXJlZCRSYWNlKSkpKw0KICAgICAgICAgICAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gYnkgUmFjZSBvZiBGZW1hbGVzIHVzaW5nIFNpemUiKSsNCiAgICAgICAgICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBNRUFOKSxjb2xvdXI9ImRlZXBwaW5rMSIsZGF0YT1EYXRhX3NleF9vY2NwX3dvbWVuKSsNCiAgICAgICAgICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBNRUFOKSxjb2xvdXI9ImJsdWUiLGRhdGE9RGF0YV9zZXhfb2NjcF9tZW4pKw0KICAgICAgICAgICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IE1FQU4pLGNvbG91cj0iZ3JlZW4iLGRhdGE9RGF0YV9vY2N1KQ0KZ2dwbG90bHkoQmFzZV9maWxsKQ0KYGBgDQpPYmVzZXJ2YXRpb25zOg0KDQoxLiBFeGNlcHQgZm9yIEFzaWFucyBhbmQgQmxhY2tzLCBhbGwgb3RoZXIgbWlub3JpdHkgZ3JvdXBzIGVhcm5lZCBzaWduaWZpY2FudGx5IGxlc3MgdGhhbiB0aGUgbWVkaWFuLiANCg0KMi4gQmxhY2sgV29tZW4gZWFybiBsZXNzIHRoYW4gV2hpdGUgd29tZW5zIGZvciBhbGwgb2NjdXBhdGlvbnMsIGV4Y2VwdCBsZWdhbC4NCg0KMy4gTGF3eWVycyB3b3VsZCBoYXZlIHRoZSBtb3N0IGVxdWFsIHBheSByZWxhdGl2ZSB0byB0aGUgcmVzdCBvZiB0aGUgb2NjdXBhdGlvbnMuDQoNCg0KRnJvbSBvdXIgYW5hbHlzaXMsIHdlIGxlYXJuZWQgdGhlIGZvbGxvd2luZyBicmVha2Rvd24gb2Ygd29tZW4gaW4gdGhlIHdvcmtmb3JjZToNCg0KTGV2ZWwgfCBSYWNlIG9mIFdvbWVuDQotLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLQ0KQmVsb3cgfCBCbGFjaywgQW1lcmljYW4gSW5kaWFuLCBUcmliZSBzcGVjaWZpZWQsIE5hdGl2ZSBIYXdhaWlhbiwgT3RoZXIsIFR3byBvciBtb3JlIHJhY2VzDQpNZWV0IHwgQXNpYW4sIFdoaXRlDQpFeGNlZWQgfCBOb25lIA0KDQoNClRocm91Z2ggdGhlc2UgcmVzdWx0cywgdGhlaXIgaXMgYSBzaWduaWZpY2FudCBnYXAgaW4gaW5jb21lIGZvciB3b21lbiByZWdhcmRsZXNzIHRvIHJhY2UuIA0KDQoNCiNBcHBlbmRpeA0KDQojIyBVc2luZyBTdXJ2ZXkgV2VpZ2h0cw0KV2Ugd2VyZSB0cnlpbmcgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IHRvIHVzZSBzdXJ2ZXkgd2VpZ2h0cy4gVG8gaGVscCBvdXIgcmVzZWFyY2ggd2UgdXNlZCBodHRwOi8vdG9waGNpdG8uYmxvZ3Nwb3QuY28uYXQvMjAxNC8wNC9zb2NpYWwtc2NpZW5jZS1nb2VzLXItd2VpZ2h0ZWQtc3VydmV5Lmh0bWwgZm9yIHJlZmVyZW5jZS4gQWxsIHNhbXBsZXMgd2VyZSBhc3NpZ25lZCBvbmUuIFRoZSBzYW1wbGUgd2l0aCBxdWFsaXRpZXMgbW9yZSBmcmVxdWVudCB3YXMgYXNzaWduZWQgYSBsb3dlciBudW1iZXIsIHZpY2UgVmVyc2EuIFJlc3BvbmRlbnRzIHRoYXQgYmVsb25nIHRvIGdyb3VwcyB0aGF0IGhhdmUgYmVlbiBzYW1wbGVkIHBlcmZlY3RseSByZWNlaXZlIGEgd2VpZ2h0IG9mIDEuIFRoaXMgc29sdXRpb24gaXMgY2FsbGVkIHBvc3Qtc3RyYXRpZmljYXRpb24sIGJlY2F1c2UgaXQgY29tcHV0ZXMgd2VpZ2h0cyBiYXNlZCBvbiBncm91cCAob3Igc3RyYXR1bSkgY2hhcmFjdGVyaXN0aWNzLCBsaWtlIHRoZSBkaXN0cmlidXRpb24gb2YgYWdlIG9yIGdlbmRlciBwcm9wb3J0aW9ucy4NCmBgYHtyfQ0KRGF0YS53ID0gc3Z5ZGVzaWduKGlkcyA9IH4xLCBkYXRhID0gRGF0YSwgd2VpZ2h0cyA9IERhdGEkV2VpZ2h0KQ0Kc3VtbWFyeShEYXRhLncpDQoNCiMgY29tcGFyaXNvbiBvZiB0aGUgc2V4IHJhdGlvcyBpbiB0aGUgdW53ZWlnaHRlZCBhbmQgdGhlIHdlaWdodGVkIGRhdGEgZnJhbWVzOg0KcHJvcC50YWJsZSh0YWJsZShEYXRhJEdlbmRlcikpDQpwcm9wLnRhYmxlKHN2eXRhYmxlKH5HZW5kZXIsIGRlc2lnbiA9IERhdGEudykpDQoNCiMgUnVuIHRoaXMgdG8gc2VlIGhvdyBpdCB3b3Jrcw0KdGFibGUoRGF0YSRHZW5kZXIpDQpzdnl0YWJsZSh+R2VuZGVyLCBkZXNpZ24gPSBEYXRhLncpDQoNCiMgVGFrZSBteSBpbnRlcmVzdGVkIHZhcmlhYmxlICdTdGF0ZScgYXMgYW4gZXhhbXBsZSwgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdW53ZWlnaHRlZCBhbmQgd2VpZ2h0ZWQgcmF0aW8gaXMgcmVhbGx5IHNtYWxsDQpzdGF0ZSA8LSBhcy5kYXRhLmZyYW1lKHByb3AudGFibGUodGFibGUoRGF0YSRTdGF0ZSkpIC0gcHJvcC50YWJsZShzdnl0YWJsZSh+U3RhdGUsIGRlc2lnbiA9IERhdGEudykpKQ0Kc3RhdGUNCg0KaW5jb21lIDwtIGFzLmRhdGEuZnJhbWUocHJvcC50YWJsZSh0YWJsZShEYXRhJEluY29tZSkpIC0gcHJvcC50YWJsZShzdnl0YWJsZSh+SW5jb21lLCBkZXNpZ24gPSBEYXRhLncpKSkNCmluY29tZQ0KDQojbWVkaWFuIHdhZ2UgZm9yIGVhY2ggb2NjdXBhdGlvbiBieSBnZW5kZXIgKGp1c3QgdG8gYWNrbm93bGVkZ2UgdGhhdCB0aGVyZSAqaXMqIGEgZ2VuZGVyIGdhcCkNCiNmYWN0b3IgbWFycmlhZ2UgYW5kIGNoYW5nZSBsYWJlbHMNCmBgYA0KRnJvbSBvdXIgcmVzdWx0cywgdGhlIHN1cnZleSB3ZWlnaHRzIHdvdWxkIGJlIGluc2lnbmlmaWNhbnQgcmVsYXRpdmUgdG8gdGhlIGRhdGEuIFRoZSBkaWZmZXJlbmNlIGZvciBlYWNoIGluY29tZSBsZXZlbCBiZXR3ZWVuIHVud2VpZ2h0ZWQgYW5kIHdlaWdodGVkIGlzIHRvbyBzbWFsbC4NCg0K